mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
627 lines
24 KiB
627 lines
24 KiB
#include <string.h>
|
|
#include "ntsdp.h"
|
|
#include "ntdis.h"
|
|
#include "ntreg.h"
|
|
|
|
#define OPCODE(x) (x << 26)
|
|
#define INSTRS(x) (x << 21)
|
|
#define INSTRT(x) (x << 16)
|
|
#define INSTRD(x) (x << 11)
|
|
#define INSTRE(x) (x << 6)
|
|
#define INSTFN(x) (x)
|
|
|
|
#define FLTFMT(x) (x << 21)
|
|
#define FLTFNC(x) (x)
|
|
|
|
typedef struct asmtabentry {
|
|
UCHAR *pszOpcode;
|
|
ULONG fInstruction;
|
|
ULONG opcodeValue;
|
|
} ASMTABENTRY, *PASMTABENTRY;
|
|
|
|
void assem(PADDR, PUCHAR);
|
|
BOOLEAN TestCharacter(UCHAR);
|
|
ULONG GetCacheCode(void);
|
|
ULONG GetReg(BOOLEAN);
|
|
LONG GetValue(BOOLEAN, ULONG);
|
|
void SkipWhite(void);
|
|
ULONG GetString(PUCHAR, ULONG);
|
|
ULONG SearchOpcode(PUCHAR);
|
|
|
|
static INSTR asmInstr;
|
|
|
|
PUCHAR pchCommand;
|
|
|
|
PUCHAR pszCacheCode[] = { "i", "d", "si", "sd" };
|
|
|
|
ASMTABENTRY asmTable[] = {
|
|
{ pszAbs_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x05L) },
|
|
{ pszAdd, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x20L) },
|
|
{ pszAdd_s, opnFdFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x00L) },
|
|
{ pszAddi, opnRtRsImm16, (ULONG) OPCODE(0x08L) },
|
|
{ pszAddiu, opnRtRsImm16, (ULONG) OPCODE(0x09L) },
|
|
{ pszAddu, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x21L) },
|
|
{ pszAnd, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x24L) },
|
|
{ pszAndi, opnRtRsImm16, (ULONG) OPCODE(0x0cL) },
|
|
{ pszBc0f, opnRel16, (ULONG) OPCODE(0x10L) + INSTRS(0x08L) + INSTRT(0x00L) },
|
|
{ pszBc0fl, opnRel16, (ULONG) OPCODE(0x10L) + INSTRS(0x08L) + INSTRT(0x02L) },
|
|
{ pszBc0t, opnRel16, (ULONG) OPCODE(0x10L) + INSTRS(0x08L) + INSTRT(0x01L) },
|
|
{ pszBc0tl, opnRel16, (ULONG) OPCODE(0x10L) + INSTRS(0x08L) + INSTRT(0x03L) },
|
|
{ pszBc1f, opnRel16, (ULONG) OPCODE(0x11L) + INSTRS(0x08L) + INSTRT(0x00L) },
|
|
{ pszBc1fl, opnRel16, (ULONG) OPCODE(0x11L) + INSTRS(0x08L) + INSTRT(0x02L) },
|
|
{ pszBc1t, opnRel16, (ULONG) OPCODE(0x11L) + INSTRS(0x08L) + INSTRT(0x01L) },
|
|
{ pszBc1tl, opnRel16, (ULONG) OPCODE(0x11L) + INSTRS(0x08L) + INSTRT(0x03L) },
|
|
{ pszBc2f, opnRel16, (ULONG) OPCODE(0x12L) + INSTRS(0x08L) + INSTRT(0x00L) },
|
|
{ pszBc2fl, opnRel16, (ULONG) OPCODE(0x12L) + INSTRS(0x08L) + INSTRT(0x02L) },
|
|
{ pszBc2t, opnRel16, (ULONG) OPCODE(0x12L) + INSTRS(0x08L) + INSTRT(0x01L) },
|
|
{ pszBc2tl, opnRel16, (ULONG) OPCODE(0x12L) + INSTRS(0x08L) + INSTRT(0x03L) },
|
|
{ pszBc3f, opnRel16, (ULONG) OPCODE(0x13L) + INSTRS(0x08L) + INSTRT(0x00L) },
|
|
{ pszBc3fl, opnRel16, (ULONG) OPCODE(0x13L) + INSTRS(0x08L) + INSTRT(0x02L) },
|
|
{ pszBc3t, opnRel16, (ULONG) OPCODE(0x13L) + INSTRS(0x08L) + INSTRT(0x01L) },
|
|
{ pszBc3tl, opnRel16, (ULONG) OPCODE(0x13L) + INSTRS(0x08L) + INSTRT(0x03L) },
|
|
{ pszBeq, opnRsRtRel16, (ULONG) OPCODE(0x04L) },
|
|
{ pszBeql, opnRsRtRel16, (ULONG) OPCODE(0x14L) },
|
|
{ pszBgez, opnRsRel16, (ULONG) OPCODE(0x01L) + INSTRT(0x01L) },
|
|
{ pszBgezal, opnRsRel16, (ULONG) OPCODE(0x01L) + INSTRT(0x11L) },
|
|
{ pszBgezall, opnRsRel16, (ULONG) OPCODE(0x01L) + INSTRT(0x13L) },
|
|
{ pszBgezl, opnRsRel16, (ULONG) OPCODE(0x01L) + INSTRT(0x03L) },
|
|
{ pszBgtz, opnRsRel16, (ULONG) OPCODE(0x07L) },
|
|
{ pszBgtzl, opnRsRel16, (ULONG) OPCODE(0x17L) },
|
|
{ pszBlez, opnRsRel16, (ULONG) OPCODE(0x06L) },
|
|
{ pszBlezl, opnRsRel16, (ULONG) OPCODE(0x16L) },
|
|
{ pszBltz, opnRsRel16, (ULONG) OPCODE(0x01L) + INSTRT(0x00L) },
|
|
{ pszBltzal, opnRsRel16, (ULONG) OPCODE(0x01L) + INSTRT(0x10L) },
|
|
{ pszBltzall, opnRsRel16, (ULONG) OPCODE(0x01L) + INSTRT(0x12L) },
|
|
{ pszBltzl, opnRsRel16, (ULONG) OPCODE(0x01L) + INSTRT(0x02L) },
|
|
{ pszBne, opnRsRtRel16, (ULONG) OPCODE(0x05L) },
|
|
{ pszBnel, opnRsRtRel16, (ULONG) OPCODE(0x15L) },
|
|
{ pszBreak, opnImm20, (ULONG) OPCODE(0x00L) + INSTFN(0x0dL) },
|
|
{ pszC_eq_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x32L) },
|
|
{ pszC_f_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x30L) },
|
|
{ pszC_le_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x3eL) },
|
|
{ pszC_lt_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x3cL) },
|
|
{ pszC_nge_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x3dL) },
|
|
{ pszC_ngl_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x3bL) },
|
|
{ pszC_ngle_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x39L) },
|
|
{ pszC_ngt_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x3fL) },
|
|
{ pszC_ole_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x36L) },
|
|
{ pszC_olt_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x34L) },
|
|
{ pszC_seq_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x3aL) },
|
|
{ pszC_sf_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x38L) },
|
|
{ pszC_ueq_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x33L) },
|
|
{ pszC_ule_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x37L) },
|
|
{ pszC_ult_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x35L) },
|
|
{ pszC_un_s, opnFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x31L) },
|
|
{ pszCache, opnCacheRightIndex, (ULONG) OPCODE(0x2fL) },
|
|
{ pszCeil_w_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x0eL) },
|
|
{ pszCfc0, opnRtRd, (ULONG) OPCODE(0x10L) + INSTRS(0x02L) },
|
|
{ pszCfc1, opnRtFs, (ULONG) OPCODE(0x11L) + INSTRS(0x02L) },
|
|
{ pszCfc2, opnRtRd, (ULONG) OPCODE(0x12L) + INSTRS(0x02L) },
|
|
{ pszCfc3, opnRtRd, (ULONG) OPCODE(0x13L) + INSTRS(0x02L) },
|
|
{ pszCop0, opnImm26, (ULONG) OPCODE(0x10L) },
|
|
{ pszCop1, opnImm26, (ULONG) OPCODE(0x11L) },
|
|
{ pszCop2, opnImm26, (ULONG) OPCODE(0x12L) },
|
|
{ pszCop3, opnImm26, (ULONG) OPCODE(0x13L) },
|
|
{ pszCtc0, opnRtRd, (ULONG) OPCODE(0x10L) + INSTRS(0x06L) },
|
|
{ pszCtc1, opnRtFs, (ULONG) OPCODE(0x11L) + INSTRS(0x06L) },
|
|
{ pszCtc2, opnRtRd, (ULONG) OPCODE(0x12L) + INSTRS(0x06L) },
|
|
{ pszCtc3, opnRtRd, (ULONG) OPCODE(0x13L) + INSTRS(0x06L) },
|
|
{ pszCvt_d_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x21L) },
|
|
{ pszCvt_e_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x22L) },
|
|
{ pszCvt_q_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x23L) },
|
|
{ pszCvt_s_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x20L) },
|
|
{ pszCvt_w_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x24L) },
|
|
{ pszDiv, opnRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x1aL) },
|
|
{ pszDiv_s, opnFdFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x03L) },
|
|
{ pszDivu, opnRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x1bL) },
|
|
{ pszEret, opnNone, (ULONG) OPCODE(0x10L) + FLTFMT(0x10L) + INSTFN(0x18L) },
|
|
{ pszFloor_w_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x0fL) },
|
|
{ pszJ, opnAddr26, (ULONG) OPCODE(0x02L) },
|
|
{ pszJal, opnAddr26, (ULONG) OPCODE(0x03L) },
|
|
{ pszJalr, opnRdOptRs, (ULONG) OPCODE(0x00L) + INSTFN(0x09L) },
|
|
{ pszJr, opnRs, (ULONG) OPCODE(0x00L) + INSTFN(0x08L) },
|
|
{ pszLb, opnRtByteIndex, (ULONG) OPCODE(0x20L) },
|
|
{ pszLbu, opnRtByteIndex, (ULONG) OPCODE(0x24L) },
|
|
{ pszLdc1, opnFtDwordIndex, (ULONG) OPCODE(0x35L) },
|
|
{ pszLdc2, opnRtDwordIndex, (ULONG) OPCODE(0x36L) },
|
|
{ pszLdc3, opnRtDwordIndex, (ULONG) OPCODE(0x37L) },
|
|
{ pszLh, opnRtWordIndex, (ULONG) OPCODE(0x21L) },
|
|
{ pszLhu, opnRtWordIndex, (ULONG) OPCODE(0x25L) },
|
|
{ pszLui, opnRtImm16, (ULONG) OPCODE(0x0fL) },
|
|
{ pszLw, opnRtDwordIndex, (ULONG) OPCODE(0x23L) },
|
|
{ pszLwc0, opnRtDwordIndex, (ULONG) OPCODE(0x30L) },
|
|
{ pszLwc1, opnFtDwordIndex, (ULONG) OPCODE(0x31L) },
|
|
{ pszLwc2, opnRtDwordIndex, (ULONG) OPCODE(0x32L) },
|
|
{ pszLwc3, opnRtDwordIndex, (ULONG) OPCODE(0x33L) },
|
|
{ pszLwl, opnRtLeftIndex, (ULONG) OPCODE(0x22L) },
|
|
{ pszLwr, opnRtRightIndex, (ULONG) OPCODE(0x26L) },
|
|
{ pszMfc0, opnRtRd, (ULONG) OPCODE(0x10L) + INSTRS(0x00L) },
|
|
{ pszMfc1, opnRtFs, (ULONG) OPCODE(0x11L) + INSTRS(0x00L) },
|
|
{ pszMfc2, opnRtRd, (ULONG) OPCODE(0x12L) + INSTRS(0x00L) },
|
|
{ pszMfc3, opnRtRd, (ULONG) OPCODE(0x13L) + INSTRS(0x00L) },
|
|
{ pszMfhi, opnRd, (ULONG) OPCODE(0x00L) + INSTFN(0x10L) },
|
|
{ pszMflo, opnRd, (ULONG) OPCODE(0x00L) + INSTFN(0x12L) },
|
|
{ pszMov_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x06L) },
|
|
{ pszMtc0, opnRtRd, (ULONG) OPCODE(0x10L) + INSTRS(0x04L) },
|
|
{ pszMtc1, opnRtFs, (ULONG) OPCODE(0x11L) + INSTRS(0x04L) },
|
|
{ pszMtc2, opnRtRd, (ULONG) OPCODE(0x12L) + INSTRS(0x04L) },
|
|
{ pszMtc3, opnRtRd, (ULONG) OPCODE(0x13L) + INSTRS(0x04L) },
|
|
{ pszMthi, opnRs, (ULONG) OPCODE(0x00L) + INSTFN(0x11L) },
|
|
{ pszMtlo, opnRs, (ULONG) OPCODE(0x00L) + INSTFN(0x13L) },
|
|
{ pszMul_s, opnFdFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x02L) },
|
|
{ pszMult, opnRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x18L) },
|
|
{ pszMultu, opnRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x19L) },
|
|
{ pszNeg_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x07L) },
|
|
{ pszNop, opnNone, (ULONG) OPCODE(0x00L) },
|
|
{ pszNor, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x27L) },
|
|
{ pszOr, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x25L) },
|
|
{ pszOri, opnRtRsImm16, (ULONG) OPCODE(0x0dL) },
|
|
{ pszRfe, opnNone, (ULONG) OPCODE(0x10L) + FLTFMT(0x10L) + INSTFN(0x10L) },
|
|
{ pszRound_w_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x0cL) },
|
|
{ pszSb, opnRtByteIndex, (ULONG) OPCODE(0x28L) },
|
|
{ pszSdc1, opnFtDwordIndex, (ULONG) OPCODE(0x3dL) },
|
|
{ pszSdc2, opnRtDwordIndex, (ULONG) OPCODE(0x3eL) },
|
|
{ pszSdc3, opnRtDwordIndex, (ULONG) OPCODE(0x3fL) },
|
|
{ pszSh, opnRtWordIndex, (ULONG) OPCODE(0x29L) },
|
|
{ pszSll, opnRdRtShift, (ULONG) OPCODE(0x00L) + INSTFN(0x00L) },
|
|
{ pszSllv, opnRdRtRs, (ULONG) OPCODE(0x00L) + INSTFN(0x04L) },
|
|
{ pszSlt, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x2aL) },
|
|
{ pszSlti, opnRtRsImm16, (ULONG) OPCODE(0x0aL) },
|
|
{ pszSltiu, opnRtRsImm16, (ULONG) OPCODE(0x0bL) },
|
|
{ pszSltu, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x2bL) },
|
|
{ pszSqrt_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x04L) },
|
|
{ pszSra, opnRdRtShift, (ULONG) OPCODE(0x00L) + INSTFN(0x03L) },
|
|
{ pszSrav, opnRdRtRs, (ULONG) OPCODE(0x00L) + INSTFN(0x07L) },
|
|
{ pszSrl, opnRdRtShift, (ULONG) OPCODE(0x00L) + INSTFN(0x02L) },
|
|
{ pszSrlv, opnRdRtRs, (ULONG) OPCODE(0x00L) + INSTFN(0x06L) },
|
|
{ pszSub, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x22L) },
|
|
{ pszSub_s, opnFdFsFt, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x01L) },
|
|
{ pszSubu, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x23L) },
|
|
{ pszSw, opnRtDwordIndex, (ULONG) OPCODE(0x2bL) },
|
|
{ pszSwc0, opnRtDwordIndex, (ULONG) OPCODE(0x38L) },
|
|
{ pszSwc1, opnFtDwordIndex, (ULONG) OPCODE(0x39L) },
|
|
{ pszSwc2, opnRtDwordIndex, (ULONG) OPCODE(0x3aL) },
|
|
{ pszSwc3, opnRtDwordIndex, (ULONG) OPCODE(0x3bL) },
|
|
{ pszSwl, opnRtLeftIndex, (ULONG) OPCODE(0x2aL) },
|
|
{ pszSwr, opnRtRightIndex, (ULONG) OPCODE(0x2eL) },
|
|
{ pszSync, opnNone, (ULONG) OPCODE(0x00L) + INSTFN(0x0fL) },
|
|
{ pszSyscall, opnNone, (ULONG) OPCODE(0x00L) + INSTFN(0x0cL) },
|
|
{ pszTeq, opnRsRtImm10, (ULONG) OPCODE(0x00L) + INSTFN(0x34L) },
|
|
{ pszTeqi, opnRsImm16, (ULONG) OPCODE(0x01L) + INSTRT(0x0cL) },
|
|
{ pszTge, opnRsRtImm10, (ULONG) OPCODE(0x00L) + INSTFN(0x30L) },
|
|
{ pszTgei, opnRsImm16, (ULONG) OPCODE(0x01L) + INSTRT(0x08L) },
|
|
{ pszTgeiu, opnRsImm16, (ULONG) OPCODE(0x01L) + INSTRT(0x09L) },
|
|
{ pszTgeu, opnRsRtImm10, (ULONG) OPCODE(0x00L) + INSTFN(0x31L) },
|
|
{ pszTlbp, opnNone, (ULONG) OPCODE(0x10L) + FLTFMT(0x10L) + INSTFN(0x08L) },
|
|
{ pszTlbr, opnNone, (ULONG) OPCODE(0x10L) + FLTFMT(0x10L) + INSTFN(0x01L) },
|
|
{ pszTlbwi, opnNone, (ULONG) OPCODE(0x10L) + FLTFMT(0x10L) + INSTFN(0x02L) },
|
|
{ pszTlbwr, opnNone, (ULONG) OPCODE(0x10L) + FLTFMT(0x10L) + INSTFN(0x06L) },
|
|
{ pszTlt, opnRsRtImm10, (ULONG) OPCODE(0x00L) + INSTFN(0x32L) },
|
|
{ pszTlti, opnRsImm16, (ULONG) OPCODE(0x01L) + INSTRT(0x0aL) },
|
|
{ pszTltiu, opnRsImm16, (ULONG) OPCODE(0x01L) + INSTRT(0x0bL) },
|
|
{ pszTltu, opnRsRtImm10, (ULONG) OPCODE(0x00L) + INSTFN(0x33L) },
|
|
{ pszTne, opnRsRtImm10, (ULONG) OPCODE(0x00L) + INSTFN(0x36L) },
|
|
{ pszTnei, opnRsImm16, (ULONG) OPCODE(0x01L) + INSTRT(0x0eL) },
|
|
{ pszTrunc_w_s, opnFdFs, (ULONG) OPCODE(0x11L) + FLTFMT(0x10L) + FLTFNC(0x0dL) },
|
|
{ pszXor, opnRdRsRt, (ULONG) OPCODE(0x00L) + INSTFN(0x26L) },
|
|
{ pszXori, opnRtRsImm16, (ULONG) OPCODE(0x0eL) }
|
|
};
|
|
|
|
#define SEARCHNUM sizeof(asmTable) / sizeof(ASMTABENTRY)
|
|
|
|
#define OPSIZE 11
|
|
|
|
/*** assem - assemble instruction
|
|
*
|
|
* Purpose:
|
|
* To assemble the instruction pointed by *poffset.
|
|
*
|
|
* Input:
|
|
* *poffset - pointer to offset to assemble
|
|
*
|
|
* Output:
|
|
* pchCommand - pointer to buffer to place assembled instruction
|
|
*
|
|
* Exceptions:
|
|
* error exit:
|
|
* BADOPCODE - unknown or bad opcode
|
|
* OPERAND - bad operand
|
|
* ALIGNMENT - bad byte alignment in operand
|
|
* DISPLACEMENT - overflow in displacement computation
|
|
* BADREG - bad register name
|
|
* EXTRACHARS - extra characters after legal instruction
|
|
* MEMORY - write failure on assembled instruction
|
|
*
|
|
* Notes:
|
|
* errors are handled by the calling program by outputting
|
|
* the error string and reprompting the user for the same
|
|
* instruction.
|
|
*
|
|
*************************************************************************/
|
|
|
|
void assem (PADDR poffset, PUCHAR pchInput)
|
|
{
|
|
UCHAR szOpcode[OPSIZE];
|
|
ULONG index;
|
|
ULONG opnum;
|
|
ULONG foperand;
|
|
LONG disp;
|
|
ULONG temp;
|
|
|
|
BOOLEAN fDouble = FALSE; // set for double float instrs
|
|
BOOLEAN fExtend = FALSE; // set for extended float instrs
|
|
BOOLEAN fQuad = FALSE; // set for quad float instrs
|
|
BOOLEAN fWord = FALSE; // set for fixed-word float instrs
|
|
|
|
pchCommand = pchInput;
|
|
|
|
// Get opcode in szOpcode with lower-case mapping.
|
|
// Return error if opcode is too large.
|
|
|
|
index = GetString(szOpcode, OPSIZE);
|
|
if (index == 0)
|
|
error(BADOPCODE);
|
|
|
|
// If last two characters are ".d", set flag for double
|
|
// and change suffix to ".s".
|
|
// If last two characters are ".e", set flag for extended
|
|
// and change suffix to ".s".
|
|
// If last two characters are ".q", set flag for quad
|
|
// and change suffix to ".s".
|
|
// If last two characters are ".w", set flag for fixed-word
|
|
// and change suffix to ".s".
|
|
|
|
if (index > 2 && szOpcode[index - 2] == '.') {
|
|
if (szOpcode[index - 1] == 'd') {
|
|
fDouble = TRUE;
|
|
szOpcode[index - 1] = 's';
|
|
}
|
|
else if (szOpcode[index - 1] == 'e') {
|
|
fExtend = TRUE;
|
|
szOpcode[index - 1] = 's';
|
|
}
|
|
else if (szOpcode[index - 1] == 'q') {
|
|
fQuad = TRUE;
|
|
szOpcode[index - 1] = 's';
|
|
}
|
|
else if (szOpcode[index - 1] == 'w') {
|
|
fWord = TRUE;
|
|
szOpcode[index - 1] = 's';
|
|
}
|
|
}
|
|
|
|
// Determine the opcode of the instruction.
|
|
|
|
opnum = SearchOpcode(szOpcode);
|
|
|
|
if (opnum == -1)
|
|
error(BADOPCODE);
|
|
|
|
asmInstr.instruction = asmTable[opnum].opcodeValue;
|
|
foperand = asmTable[opnum].fInstruction;
|
|
|
|
// Using foperand flags, build the instruction
|
|
|
|
if (foperand & opnCache) {
|
|
asmInstr.immed_instr.RT = GetCacheCode();
|
|
if (!TestCharacter(','))
|
|
error(OPERAND);
|
|
}
|
|
|
|
if (foperand & opnPreRt) {
|
|
asmInstr.immed_instr.RT = GetReg(FALSE);
|
|
if (!TestCharacter(','))
|
|
error(BADREG);
|
|
}
|
|
|
|
if (foperand & opnRd)
|
|
asmInstr.special_instr.RD = GetReg(FALSE);
|
|
|
|
if (foperand & opnFd)
|
|
asmInstr.float_instr.FD = GetReg(TRUE);
|
|
|
|
if (foperand & opnRdOptRs) {
|
|
temp = GetReg(FALSE);
|
|
if (TestCharacter(',')) {
|
|
asmInstr.special_instr.RD = temp;
|
|
asmInstr.special_instr.RS = GetReg(FALSE);
|
|
}
|
|
else {
|
|
asmInstr.special_instr.RD = 0x1f;
|
|
asmInstr.special_instr.RS = temp;
|
|
}
|
|
}
|
|
|
|
if (foperand & opnRdComma)
|
|
if (!TestCharacter(','))
|
|
error(BADREG);
|
|
|
|
if (foperand & opnRs)
|
|
asmInstr.immed_instr.RS = GetReg(FALSE);
|
|
|
|
if (foperand & opnFs)
|
|
asmInstr.float_instr.FS = GetReg(TRUE);
|
|
|
|
if (foperand & opnRsComma)
|
|
if (!TestCharacter(','))
|
|
error(BADREG);
|
|
|
|
if (foperand & opnRt)
|
|
asmInstr.immed_instr.RT = GetReg(FALSE);
|
|
|
|
if (foperand & opnFt)
|
|
asmInstr.float_instr.FT = GetReg(TRUE);
|
|
|
|
if (foperand & opnRtComma)
|
|
if (!TestCharacter(','))
|
|
error(BADREG);
|
|
|
|
if (foperand & opnPostRs)
|
|
asmInstr.immed_instr.RS = GetReg(FALSE);
|
|
|
|
if (foperand & opnImm10)
|
|
asmInstr.trap_instr.Value = GetValue(TRUE, 10);
|
|
|
|
if (foperand & opnImm16)
|
|
asmInstr.immed_instr.Value = GetValue(TRUE, 16);
|
|
|
|
if (foperand & opnRel16) {
|
|
disp = GetValue(FALSE, 32) - (Flat(*poffset) + sizeof(ULONG));
|
|
if (disp & 0x00000003)
|
|
error(ALIGNMENT);
|
|
disp >>= 2;
|
|
if (disp > 0xffff || disp < -0x10000)
|
|
error(DISPLACEMENT);
|
|
asmInstr.immed_instr.Value = disp;
|
|
}
|
|
|
|
if (foperand & opnImm20)
|
|
asmInstr.break_instr.Value = GetValue(FALSE, 10);
|
|
|
|
if (foperand & opnImm26)
|
|
asmInstr.jump_instr.Target = GetValue(FALSE, 26);
|
|
|
|
if (foperand & opnAddr26) {
|
|
disp = GetValue(FALSE, 32) - (Flat(*poffset) & 0xf0000000);
|
|
if (disp & 0x00000003)
|
|
error(ALIGNMENT);
|
|
disp >>= 2;
|
|
if (disp > 0x2ffffff || disp < -0x3000000)
|
|
error(DISPLACEMENT);
|
|
asmInstr.jump_instr.Target = disp;
|
|
}
|
|
|
|
if (foperand & opnAnyIndex) {
|
|
if (!TestCharacter('(')) {
|
|
asmInstr.immed_instr.Value = GetValue(TRUE, 16);
|
|
if (!TestCharacter('('))
|
|
error(OPERAND);
|
|
}
|
|
asmInstr.immed_instr.RS = GetReg(FALSE);
|
|
if (!TestCharacter(')'))
|
|
error(OPERAND);
|
|
}
|
|
|
|
if (foperand & opnShift)
|
|
asmInstr.special_instr.RE = GetValue(FALSE, 5);
|
|
|
|
if (!TestCharacter('\0'))
|
|
error(EXTRACHARS);
|
|
pchCommand--;
|
|
|
|
if (fDouble)
|
|
asmInstr.float_instr.Format = 0x11;
|
|
else if (fExtend)
|
|
asmInstr.float_instr.Format = 0x12;
|
|
else if (fQuad)
|
|
asmInstr.float_instr.Format = 0x13;
|
|
else if (fWord)
|
|
asmInstr.float_instr.Format = 0x14;
|
|
|
|
#if 0
|
|
printf("Op <%s> is <%s>\n", szOpcode, asmTable[opnum].pszOpcode);
|
|
printf("double:%d - extend:%d - quad:%d - word:%d\n",
|
|
fDouble, fExtend, fQuad, fWord);
|
|
printf("assembly word %08lx - ", asmInstr.instruction);
|
|
printf("%02lx %02lx %02lx %02lx %02lx\n",
|
|
asmInstr.special_instr.Opcode,
|
|
asmInstr.special_instr.RS,
|
|
asmInstr.special_instr.RT,
|
|
asmInstr.special_instr.RD,
|
|
asmInstr.special_instr.RE,
|
|
asmInstr.special_instr.Funct);
|
|
printf("remaining string: <%s>\n", pchCommand);
|
|
#endif
|
|
|
|
if (!SetMemDword(poffset, asmInstr.instruction))
|
|
error(MEMORY);
|
|
Flat(*poffset) += sizeof(ULONG);
|
|
}
|
|
|
|
BOOLEAN TestCharacter (UCHAR ch)
|
|
{
|
|
SkipWhite();
|
|
if (ch == *pchCommand) {
|
|
pchCommand++;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
ULONG GetCacheCode (void)
|
|
{
|
|
ULONG index;
|
|
UCHAR szCode[4];
|
|
|
|
SkipWhite();
|
|
if (!GetString(szCode, 3))
|
|
error(OPERAND);
|
|
for (index = 0; index < 4; index++)
|
|
if (!strcmp(szCode, pszCacheCode[index]))
|
|
break;
|
|
if (index == 4)
|
|
error(OPERAND);
|
|
|
|
return index;
|
|
}
|
|
|
|
/*** GetReg - get register index
|
|
*
|
|
* Purpose:
|
|
* From reading the command line, return the register index.
|
|
* Legal values are "zero","AT","v0","v1","a0"..."a3","t0"..."t7",
|
|
* "s0"..."s8","k0","k1","gp","sp","ra" for fixed registers.
|
|
* Legal values are "f0"..."f31" for floating registers.
|
|
*
|
|
* Input:
|
|
* pchCommand - present command line position
|
|
*
|
|
* Returns:
|
|
* index of fixed or float register
|
|
*
|
|
* Exceptions:
|
|
* error(BADREG) - bad register name
|
|
*
|
|
*************************************************************************/
|
|
|
|
ULONG GetReg (BOOLEAN fFloat)
|
|
{
|
|
UCHAR szRegOp[5];
|
|
ULONG index;
|
|
ULONG regindex;
|
|
|
|
SkipWhite();
|
|
if (!GetString(szRegOp, 5))
|
|
error(BADREG);
|
|
regindex = fFloat ? FLTBASE : REGBASE;
|
|
for (index = 0; index < 32; index++)
|
|
if (!strcmp(szRegOp, pszReg[regindex++]))
|
|
return index;
|
|
error(BADREG);
|
|
}
|
|
|
|
/*** GetValue - get value from command line
|
|
*
|
|
* Purpose:
|
|
* Use GetExpression to evaluate the next
|
|
* expression in the command line.
|
|
*
|
|
* Input:
|
|
* pchCommand - present command line position
|
|
* fSigned - TRUE if signed value
|
|
* FALSE if unsigned value
|
|
* bitsize - size of value allowed
|
|
*
|
|
* Returns:
|
|
* returns value computed
|
|
*
|
|
* Exceptions:
|
|
* error exit: OVERFLOW - value too large for bitsize
|
|
*
|
|
*************************************************************************/
|
|
|
|
LONG GetValue (BOOLEAN fSigned, ULONG bitsize)
|
|
{
|
|
ULONG value;
|
|
|
|
SkipWhite();
|
|
value = GetExpression();
|
|
if ((value > (ULONG)(1L << bitsize) - 1) &&
|
|
(!fSigned || (value < (ULONG)(-1L << (bitsize - 1)))))
|
|
error(OVERFLOW);
|
|
return (long) value;
|
|
}
|
|
|
|
/*** SkipWhite - skip white-space
|
|
*
|
|
* Purpose:
|
|
* To advance pchCommand over any spaces or tabs.
|
|
*
|
|
* Input:
|
|
* *pchCommand - present command line position
|
|
*
|
|
*************************************************************************/
|
|
|
|
void SkipWhite (void)
|
|
{
|
|
while (*pchCommand == ' ' || *pchCommand == '\t')
|
|
pchCommand++;
|
|
}
|
|
|
|
/*** GetString - get string from command line
|
|
*
|
|
* Purpose:
|
|
* Build a lower-case mapped string of maximum size maxcnt
|
|
* at the string pointed by *psz.
|
|
*
|
|
* Input:
|
|
* *pchCommand - present command line position
|
|
* maxcnt - maximum size of string allowed
|
|
*
|
|
* Output:
|
|
* *psz - output string in lower case
|
|
*
|
|
* Returns:
|
|
* size of string if under maximum else 0
|
|
*
|
|
* Notes:
|
|
* if string exceeds maximum size, the extra characters
|
|
* are still processed, but ignored.
|
|
*
|
|
*************************************************************************/
|
|
|
|
ULONG GetString (PUCHAR psz, ULONG maxcnt)
|
|
{
|
|
UCHAR ch;
|
|
ULONG count = 0;
|
|
|
|
SkipWhite();
|
|
ch = (UCHAR)tolower(*pchCommand);
|
|
while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') ||
|
|
ch == '.') {
|
|
if (++count < maxcnt)
|
|
*psz++ = ch;
|
|
ch = (UCHAR)*++pchCommand;
|
|
ch = (UCHAR)tolower(ch);
|
|
}
|
|
if (count >= maxcnt)
|
|
return 0;
|
|
*psz = '\0';
|
|
return count;
|
|
}
|
|
|
|
/*** SearchOpcode - search for opcode
|
|
*
|
|
* Purpose:
|
|
* Search the opcode table for a match with the string
|
|
* pointed by *pszOp.
|
|
*
|
|
* Input:
|
|
* *pszOp - string to search as opcode
|
|
*
|
|
* Returns:
|
|
* if not -1, index of match entry in opcode table
|
|
* if -1, not found
|
|
*
|
|
*************************************************************************/
|
|
|
|
ULONG SearchOpcode (PUCHAR pszop)
|
|
{
|
|
ULONG low = 0;
|
|
ULONG mid;
|
|
ULONG high = SEARCHNUM - 1;
|
|
ULONG match;
|
|
|
|
while (low <= high) {
|
|
mid = (low + high) / 2;
|
|
match = (ULONG)strcmp(pszop, asmTable[mid].pszOpcode);
|
|
if (match == -1)
|
|
high = mid - 1;
|
|
else if (match == 1)
|
|
low = mid + 1;
|
|
else
|
|
return mid;
|
|
}
|
|
return (ULONG) -1;
|
|
}
|