Skip to content

Commit

Permalink
RV32F/RV64F instruction set
Browse files Browse the repository at this point in the history
  • Loading branch information
makigumo committed Dec 11, 2016
1 parent 1546ad7 commit 5de0517
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 45 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ Supported instruction sets:
* [x] RV64M Standard Extension
* [x] RV32A Standard Extension
* [x] RV64A Standard Extension
* [ ] RV32F Standard Extension
* [ ] RV64F Standard Extension
* [x] RV32F Standard Extension
* [x] RV64F Standard Extension
* [ ] RV32D Standard Extension
* [ ] RV64D Standard Extension
* [x] Trap-Return Instructions
Expand Down
68 changes: 46 additions & 22 deletions RISCV/RISCVCtx.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,56 +293,80 @@ static inline void populateAMO(DisasmStruct *disasm, uint32_t insn, const char *
disasm->operand[2].accessMode = DISASM_ACCESS_READ;
}

static inline void populateFP(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
static inline void populateFP_2reg(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
strcpy(disasm->instruction.mnemonic, mnemonic);
disasm->operand[0].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[0].type |= getFpuRegMask(getRD(insn));
disasm->operand[0].accessMode = DISASM_ACCESS_WRITE;
disasm->operand[1].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[1].type |= getFpuRegMask(getRS1(insn));
disasm->operand[1].accessMode = DISASM_ACCESS_READ;
disasm->operand[2].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[2].type |= getFpuRegMask(getRS2(insn));
disasm->operand[2].accessMode = DISASM_ACCESS_READ;
if (getRoundingMode(insn) < 0b111) {
disasm->operand[3].type = DISASM_OPERAND_CONSTANT_TYPE | DISASM_OPERAND_ROUNDING_MODE;
disasm->operand[3].immediateValue = getRoundingMode(insn);
disasm->operand[3].accessMode = DISASM_ACCESS_READ;
}
}

static inline void populateFPR4(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
static inline void populateFp_gp_fp(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
strcpy(disasm->instruction.mnemonic, mnemonic);
disasm->operand[0].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[0].type |= getFpuRegMask(getRD(insn));
disasm->operand[0].type |= getRegMask(getRD(insn));
disasm->operand[0].accessMode = DISASM_ACCESS_WRITE;
disasm->operand[1].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[1].type |= getFpuRegMask(getRS1(insn));
disasm->operand[1].accessMode = DISASM_ACCESS_READ;
disasm->operand[2].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[2].type |= getFpuRegMask(getRS2(insn));
disasm->operand[2].accessMode = DISASM_ACCESS_READ;
disasm->operand[3].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[3].type |= getFpuRegMask(getRS3(insn));
disasm->operand[3].accessMode = DISASM_ACCESS_READ;
}

static inline void populateFp_gp_fp_with_rm(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
populateFp_gp_fp(disasm, insn, mnemonic);
if (getRoundingMode(insn) < 0b111) {
disasm->operand[4].type = DISASM_OPERAND_CONSTANT_TYPE | DISASM_OPERAND_ROUNDING_MODE;
disasm->operand[4].immediateValue = getRoundingMode(insn);
disasm->operand[4].accessMode = DISASM_ACCESS_READ;
disasm->operand[2].type = DISASM_OPERAND_CONSTANT_TYPE | DISASM_OPERAND_ROUNDING_MODE;
disasm->operand[2].immediateValue = getRoundingMode(insn);
disasm->operand[2].accessMode = DISASM_ACCESS_READ;
}
}

static inline void populateFPCVT(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
static inline void populateFp_fp_gp(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
strcpy(disasm->instruction.mnemonic, mnemonic);
disasm->operand[0].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[0].type |= getFpuRegMask(getRD(insn));
disasm->operand[0].accessMode = DISASM_ACCESS_WRITE;
disasm->operand[1].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[1].type |= getFpuRegMask(getRS1(insn));
disasm->operand[1].type |= getRegMask(getRS1(insn));
disasm->operand[1].accessMode = DISASM_ACCESS_READ;
}

static inline void populateFpRoundingMode(DisasmOperand *op, uint32_t insn) {
uint8_t roundingMode = getRoundingMode(insn);
if (roundingMode < 0b111 /* dynamic */) {
op->type = DISASM_OPERAND_CONSTANT_TYPE | DISASM_OPERAND_ROUNDING_MODE;
op->immediateValue = roundingMode;
op->accessMode = DISASM_ACCESS_READ;
}
}

static inline void populateFp_fp_gp_with_rm(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
populateFp_fp_gp(disasm, insn, mnemonic);
populateFpRoundingMode(&disasm->operand[2], insn);
}

static inline void populateFp_3reg(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
populateFP_2reg(disasm, insn, mnemonic);
disasm->operand[2].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[2].type |= getFpuRegMask(getRS2(insn));
disasm->operand[2].accessMode = DISASM_ACCESS_READ;
}

static inline void populateFp_3reg_with_rm(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
populateFp_3reg(disasm, insn, mnemonic);
populateFpRoundingMode(&disasm->operand[3], insn);
}

static inline void populateFp_R4(DisasmStruct *disasm, uint32_t insn, const char *mnemonic) {
populateFp_3reg(disasm, insn, mnemonic);
disasm->operand[3].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[3].type |= getFpuRegMask(getRS3(insn));
disasm->operand[3].accessMode = DISASM_ACCESS_READ;
populateFpRoundingMode(&disasm->operand[4], insn);
}


static NSString *getRoundingModeName(int64_t rm) {
switch (rm) {
case 0b000:
Expand Down
78 changes: 57 additions & 21 deletions RISCV/RISCVCtx.m
Original file line number Diff line number Diff line change
Expand Up @@ -1130,16 +1130,16 @@ - (int)disassembleSingleInstruction:(DisasmStruct *)disasm usingProcessorMode:(N
case OPCODE_FP:
switch (funct7) {
case 0b0000000 /* FADD.S */:
populateFP(disasm, insncode, "fadd.s");
populateFp_3reg_with_rm(disasm, insncode, "fadd.s");
break;
case 0b0000100 /* FSUB.S */:
populateFP(disasm, insncode, "fsub.s");
populateFp_3reg_with_rm(disasm, insncode, "fsub.s");
break;
case 0b0001000 /* FMUL.S */:
populateFP(disasm, insncode, "fmul.s");
populateFp_3reg_with_rm(disasm, insncode, "fmul.s");
break;
case 0b0001100 /* FDIV.S */:
populateFP(disasm, insncode, "fdiv.s");
populateFp_3reg_with_rm(disasm, insncode, "fdiv.s");
break;
case 0b0101100 /* FSQRT.S */:
strcpy(disasm->instruction.mnemonic, "fsqrt.s");
Expand All @@ -1149,89 +1149,125 @@ - (int)disassembleSingleInstruction:(DisasmStruct *)disasm usingProcessorMode:(N
disasm->operand[1].type = DISASM_OPERAND_REGISTER_TYPE;
disasm->operand[1].type |= getFpuRegMask(src1_reg);
disasm->operand[1].accessMode = DISASM_ACCESS_READ;
if (getRoundingMode(insncode) > 0) {
disasm->operand[3].type = DISASM_OPERAND_CONSTANT_TYPE | DISASM_OPERAND_ROUNDING_MODE;
disasm->operand[3].immediateValue = getRoundingMode(insncode);
disasm->operand[3].accessMode = DISASM_ACCESS_READ;
if (getRoundingMode(insncode) < 0b111 /* dynamic */) {
disasm->operand[2].type = DISASM_OPERAND_CONSTANT_TYPE | DISASM_OPERAND_ROUNDING_MODE;
disasm->operand[2].immediateValue = getRoundingMode(insncode);
disasm->operand[2].accessMode = DISASM_ACCESS_READ;
}
break;
case 0b0010000 /* FSGN */:
switch (funct3) /* rm */ {
case 0b000 /* FSGNJ.S */:
populateFP(disasm, insncode, "fsgnj.s");
if (src2_reg == src1_reg) {
// FSGNJ.S rx, ry, ry = FMV.S rx, ry
populateFP_2reg(disasm, insncode, "fmv.s");
} else {
populateFp_3reg(disasm, insncode, "fsgnj.s");
}
break;
case 0b001 /* FSGNJN.S */:
populateFP(disasm, insncode, "fsgnjn.s");
if (src2_reg == src1_reg) {
// FSGNJN.S rx, ry, ry = FNEG.S rx, ry
populateFP_2reg(disasm, insncode, "fneg.s");
} else {
populateFp_3reg(disasm, insncode, "fsgnjn.s");
}
break;
case 0b010 /* FSGNJX.S */:
populateFP(disasm, insncode, "fsgnjx.s");
if (src2_reg == src1_reg) {
// FSGNJX.S rx, ry, ry = FABS.S rx, ry
populateFP_2reg(disasm, insncode, "fabs.s");
} else {
populateFp_3reg(disasm, insncode, "fsgnjx.s");
}
break;
}
break;
case 0b0010100 /* FMIN/FMAX */:
switch (funct3) /* rm */ {
case 0b000 /* FMIN.S */:
populateFP(disasm, insncode, "fmin.s");
populateFp_3reg(disasm, insncode, "fmin.s");
break;
case 0b001 /* FMAX.S */:
populateFP(disasm, insncode, "fmax.s");
populateFp_3reg(disasm, insncode, "fmax.s");
break;
}
break;
case 0b1100000 /* FCVT */:
switch (funct3) /* rm */ {
case 0b000 /* FCVT.W.S */:
populateFPCVT(disasm, insncode, "fcvt.w.s");
switch (src2_reg) /* */ {
case 0b00000 /* FCVT.W.S */:
populateFp_gp_fp_with_rm(disasm, insncode, "fcvt.w.s");
break;
case 0b00001 /* FCVT.WU.S */:
populateFp_gp_fp_with_rm(disasm, insncode, "fcvt.wu.s");
break;
case 0b001 /* FCVT.WU.S */:
case 0b00010 /* FCVT.L.S */:
populateFp_gp_fp_with_rm(disasm, insncode, "fcvt.l.s");
break;
case 0b00011 /* FCVT.L.S */:
populateFp_gp_fp_with_rm(disasm, insncode, "fcvt.lu.s");
break;
}
break;
case 0b1110000:
switch (funct3) {
case 0b000 /* FMV.X.S */:
populateFp_gp_fp(disasm, insncode, "fmv.x.s");
break;
case 0b001 /* FCLASS.S */:
populateFp_gp_fp(disasm, insncode, "fclass.s");
break;
}
break;
case 0b1010000:
switch (funct3) {
case 0b010 /* FEQ.S */:
populateFp_3reg(disasm, insncode, "feq.s");
break;
case 0b001 /* FLT.S */:
populateFp_3reg(disasm, insncode, "flt.s");
break;
case 0b000 /* FLE.S */:
populateFp_3reg(disasm, insncode, "fle.s");
break;
}
break;
case 0b1101000:
switch (src2_reg) {
case 0b00000 /* FCVT.S.W */:
populateFp_fp_gp_with_rm(disasm, insncode, "fcvt.s.w");
break;
case 0b00001 /* FCVT.S.WU */:
populateFp_fp_gp_with_rm(disasm, insncode, "fcvt.s.wu");
break;
case 0b00010 /* FCVT.S.L */:
populateFp_fp_gp_with_rm(disasm, insncode, "fcvt.s.l");
break;
case 0b00011 /* FCVT.S.LU */:
populateFp_fp_gp_with_rm(disasm, insncode, "fcvt.s.lu");
break;
}
break;
case 0b1111000 /* FMV.S.X */:
populateFp_fp_gp(disasm, insncode, "fmv.x.s");
break;
}
break;

case OPCODE_FMADD:
populateFPR4(disasm, insncode, "fmadd.s");
populateFp_R4(disasm, insncode, "fmadd.s");
break;

case OPCODE_FMSUB:
populateFPR4(disasm, insncode, "fmsub.s");
populateFp_R4(disasm, insncode, "fmsub.s");
break;

case OPCODE_FNMADD:
populateFPR4(disasm, insncode, "fnmadd.s");
populateFp_R4(disasm, insncode, "fnmadd.s");
break;

case OPCODE_FNMSUB:
populateFPR4(disasm, insncode, "fnmsub.s");
populateFp_R4(disasm, insncode, "fnmsub.s");
break;

default:
Expand Down

0 comments on commit 5de0517

Please sign in to comment.