/// <summary> /// 引数で渡された32bit長の命令をデコードし、cpuで実行する /// </summary> /// <param name="instruction">32bit長の命令</param> /// <param name="cpu">命令を実行するRV32CPU</param> /// <returns>実行の成否</returns> internal protected override bool Exec(UInt32[] ins) { bool result = false; // 命令の0~1bit目が "11" でない場合は対象なし if ((ins[0] & 0b11U) != 0b11U) { return(result); } FPRegister rd = (FPRegister)ins[1], rs1 = (FPRegister)ins[3], rs2 = (FPRegister)ins[4], rs3 = (FPRegister)((ins[5] >> 2) | (ins[6] << 4)); Opcode opcode = (Opcode)ins[0]; Funct3 funct3 = (Funct3)ins[2]; Funct5 funct5 = (Funct5)(ins[5] >> 2 | (ins[6] << 4)); FloatRoundingMode frm = (FloatRoundingMode)ins[2]; Int32 immediate = 0; RV32_DoubleFpu fpu; RV32_FloatPointLsu lsu; switch (opcode) { case Opcode.fl when funct3 == Funct3.fld_fsd: // fld命令 immediate = GetImmediate('I', ins); lsu = (RV32_FloatPointLsu)Decoder.Lsu(typeof(RV32_FloatPointLsu)); result = lsu.Fld(rd, (Register)rs1, immediate); break; case Opcode.fs when funct3 == Funct3.fld_fsd: // fsd命令 immediate = GetImmediate('S', ins); lsu = (RV32_FloatPointLsu)Decoder.Lsu(typeof(RV32_FloatPointLsu)); result = lsu.Fsd((Register)rs1, rs2, immediate); break; case Opcode.fmadd when(ins[5]& 0x3U) == 0x1U: // fmaddd命令 fpu = (RV32_DoubleFpu)Decoder.Alu(typeof(RV32_DoubleFpu)); result = fpu.FmaddD(rd, rs1, rs2, rs3, frm); break; case Opcode.fmsub when(ins[5]& 0x3U) == 0x1U: // fmsubd命令 fpu = (RV32_DoubleFpu)Decoder.Alu(typeof(RV32_DoubleFpu)); result = fpu.FmsubD(rd, rs1, rs2, rs3, frm); break; case Opcode.fnmadd when(ins[5]& 0x3U) == 0x1U: // fnmaddd命令 fpu = (RV32_DoubleFpu)Decoder.Alu(typeof(RV32_DoubleFpu)); result = fpu.FnmaddD(rd, rs1, rs2, rs3, frm); break; case Opcode.fnmsub when(ins[5]& 0x3U) == 0x1U: // fnmsubd命令 fpu = (RV32_DoubleFpu)Decoder.Alu(typeof(RV32_DoubleFpu)); result = fpu.FnmsubD(rd, rs1, rs2, rs3, frm); break; case Opcode.fmiscOp when(ins[5]& 0x3U) == 0x1U: // Double Float-Point Op系命令(算術論理演算) fpu = (RV32_DoubleFpu)Decoder.Alu(typeof(RV32_DoubleFpu)); switch (funct5) { case Funct5.fadd: // faddd命令 result = fpu.FaddD(rd, rs1, rs2, frm); break; case Funct5.fsub: // fsubd命令 result = fpu.FsubD(rd, rs1, rs2, frm); break; case Funct5.fmul: // fmuld命令 result = fpu.FmulD(rd, rs1, rs2, frm); break; case Funct5.fdiv: // fdivd命令 result = fpu.FdivD(rd, rs1, rs2, frm); break; case Funct5.fsqrt: // fsqrtd命令 result = fpu.FsqrtD(rd, rs1, frm); break; case Funct5.fsgnj: switch (funct3) { case Funct3.fsgnj: // fsgnjd命令 result = fpu.FsgnjD(rd, rs1, rs2); break; case Funct3.fsgnjn: // fsgnjnd命令 result = fpu.FsgnjnD(rd, rs1, rs2); break; case Funct3.fsgnjx: // fsgnjxd命令 result = fpu.FsgnjxD(rd, rs1, rs2); break; } break; case Funct5.fmin_fmax: switch (funct3) { case Funct3.fmin: // fmind命令 result = fpu.FminD(rd, rs1, rs2); break; case Funct3.fmax: // fmaxd命令 result = fpu.FmaxD(rd, rs1, rs2); break; } break; case Funct5.fcompare: switch (funct3) { case Funct3.fcompare_eq: // feqd命令 result = fpu.FeqD((Register)rd, rs1, rs2); break; case Funct3.fcompare_lt: // fltd命令 result = fpu.FltD((Register)rd, rs1, rs2); break; case Funct3.fcompare_le: // fled命令 result = fpu.FleD((Register)rd, rs1, rs2); break; } break; case Funct5.fcvttoW: switch (ins[4]) { case 0x0: // fcvtwd命令 result = fpu.FcvtWD((Register)rd, rs1, frm); break; case 0x1: // fcvtwud命令 result = fpu.FcvtWUD((Register)rd, rs1, frm); break; } break; case Funct5.fcvtfromW: switch (ins[4]) { case 0x0: // fcvtdw命令 result = fpu.FcvtDW(rd, (Register)rs1, frm); break; case 0x1: // fcvtdwu命令 result = fpu.FcvtDWU(rd, (Register)rs1, frm); break; } break; case Funct5.fmvXW_fclass: // fclassd命令 result = fpu.FclassD((Register)rd, rs1); break; case Funct5.fcvtSD: // fcvtds命令 result = fpu.FcvtDS(rd, rs1, frm); break; } break; case Opcode.fmiscOp when(ins[5]& 0x3U) == 0x0U && funct5 == Funct5.fcvtSD: // fcvtsd命令 fpu = (RV32_DoubleFpu)Decoder.Alu(typeof(RV32_DoubleFpu)); result = fpu.FcvtSD(rd, rs1, frm); break; } return(result); }
/// <summary> /// 引数で渡された32bit長の命令をデコードし、cpuで実行する /// </summary> /// <param name="instruction">32bit長の命令</param> /// <param name="cpu">命令を実行するRV32CPU</param> /// <returns>実行の成否</returns> internal protected override bool Exec(UInt32[] ins) { bool result = false; // 命令の0~1bit目が "11" でない場合は対象なし if ((ins[0] & 0b11U) != 0b11U) { return(result); } FPRegister rd = (FPRegister)ins[1], rs1 = (FPRegister)ins[3], rs2 = (FPRegister)ins[4], rs3 = (FPRegister)((ins[5] >> 2) | (ins[6] << 4)); Opcode opcode = (Opcode)ins[0]; Funct3 funct3 = (Funct3)ins[2]; Funct5 funct5 = (Funct5)(ins[5] >> 2 | (ins[6] << 4)); FloatRoundingMode frm = (FloatRoundingMode)ins[2]; Int32 immediate = 0; RV32_SingleFpu fpu; RV32_FloatPointLsu lsu; switch (opcode) { case Opcode.fl when funct3 == Funct3.flw_fsw: // flw命令 immediate = GetImmediate('I', ins); lsu = (RV32_FloatPointLsu)Decoder.Lsu(typeof(RV32_FloatPointLsu)); result = lsu.Flw(rd, (Register)rs1, immediate); break; case Opcode.fs when funct3 == Funct3.flw_fsw: // fsw命令 immediate = GetImmediate('S', ins); lsu = (RV32_FloatPointLsu)Decoder.Lsu(typeof(RV32_FloatPointLsu)); result = lsu.Fsw((Register)rs1, rs2, immediate); break; case Opcode.fmadd when(ins[5]& 0x3U) == 0x0U: // fmadds命令 fpu = (RV32_SingleFpu)Decoder.Alu(typeof(RV32_SingleFpu)); result = fpu.FmaddS(rd, rs1, rs2, rs3, frm); break; case Opcode.fmsub when(ins[5]& 0x3U) == 0x0U: // fmsubs命令 fpu = (RV32_SingleFpu)Decoder.Alu(typeof(RV32_SingleFpu)); result = fpu.FmsubS(rd, rs1, rs2, rs3, frm); break; case Opcode.fnmadd when(ins[5]& 0x3U) == 0x0U: // fnmadds命令 fpu = (RV32_SingleFpu)Decoder.Alu(typeof(RV32_SingleFpu)); result = fpu.FnmaddS(rd, rs1, rs2, rs3, frm); break; case Opcode.fnmsub when(ins[5]& 0x3U) == 0x0U: // fnmsubs命令 fpu = (RV32_SingleFpu)Decoder.Alu(typeof(RV32_SingleFpu)); result = fpu.FnmsubS(rd, rs1, rs2, rs3, frm); break; case Opcode.fmiscOp when(ins[5]& 0x3U) == 0x0U: // Single Float-Point Op系命令(算術論理演算) fpu = (RV32_SingleFpu)Decoder.Alu(typeof(RV32_SingleFpu)); switch (funct5) { case Funct5.fadd: // fadds命令 result = fpu.FaddS(rd, rs1, rs2, frm); break; case Funct5.fsub: // fsubs命令 result = fpu.FsubS(rd, rs1, rs2, frm); break; case Funct5.fmul: // fmuls命令 result = fpu.FmulS(rd, rs1, rs2, frm); break; case Funct5.fdiv: // fmuls命令 result = fpu.FdivS(rd, rs1, rs2, frm); break; case Funct5.fsqrt: // fsqrts命令 result = fpu.FsqrtS(rd, rs1, frm); break; case Funct5.fsgnj: switch (funct3) { case Funct3.fsgnj: // fsgnjs命令 result = fpu.FsgnjS(rd, rs1, rs2); break; case Funct3.fsgnjn: // fsgnjns命令 result = fpu.FsgnjnS(rd, rs1, rs2); break; case Funct3.fsgnjx: // fsgnjxs命令 result = fpu.FsgnjxS(rd, rs1, rs2); break; } break; case Funct5.fmin_fmax: switch (funct3) { case Funct3.fmin: // fmins命令 result = fpu.FminS(rd, rs1, rs2); break; case Funct3.fmax: // fmaxs命令 result = fpu.FmaxS(rd, rs1, rs2); break; } break; case Funct5.fcompare: switch (funct3) { case Funct3.fcompare_eq: // feqs命令 result = fpu.FeqS((Register)rd, rs1, rs2); break; case Funct3.fcompare_lt: // flts命令 result = fpu.FltS((Register)rd, rs1, rs2); break; case Funct3.fcompare_le: // fles命令 result = fpu.FleS((Register)rd, rs1, rs2); break; } break; case Funct5.fcvttoW: switch (ins[4]) { case 0x0: // fcnvws命令 result = fpu.FcvtWS((Register)rd, rs1, frm); break; case 0x1: // fcnvwus命令 result = fpu.FcvtWUS((Register)rd, rs1, frm); break; } break; case Funct5.fcvtfromW: switch (ins[4]) { case 0x0: // fcnvsw命令 result = fpu.FcvtSW(rd, (Register)rs1, frm); break; case 0x1: // fcnvswu命令 result = fpu.FcvtSWU(rd, (Register)rs1, frm); break; } break; case Funct5.fmvXW_fclass: if (funct3 == (Funct3)0b000u) // fmvxw命令 { result = fpu.FmvXW((Register)rd, rs1); } else if (funct3 == (Funct3)0b001u) // fclasss命令 { result = fpu.FclassS((Register)rd, rs1); } break; case Funct5.fmvWX: // fmvwx命令 result = fpu.FmvWX(rd, (Register)rs1); break; } break; } return(result); }
/// <summary> /// 引数で渡された32bit長の命令をデコードし、cpuで実行する /// </summary> /// <param name="instruction">32bit長の命令</param> /// <param name="cpu">命令を実行するRV32CPU</param> /// <returns>実行の成否</returns> internal protected override bool Exec(UInt32[] ins) { bool result = false; // 命令の0~1bit目が "11" でない場合は対象なし if ((ins[0] & 0b11U) != 0b11U) { return(result); } Register rd = (Register)ins[1], rs1 = (Register)ins[3], rs2 = (Register)ins[4]; Opcode opcode = (Opcode)ins[0]; Funct3 funct3 = (Funct3)ins[2]; Funct5 funct5 = (Funct5)((ins[5] >> 2) + (ins[6] << 4)); RV32_AmoLsu lsu; if (opcode == Opcode.amo && funct3 == Funct3.amo) // 不可分命令 { lsu = (RV32_AmoLsu)Decoder.Lsu(typeof(RV32_AmoLsu)); bool ac = (ins[5] & 0b10) > 0, rl = (ins[5] & 0b01) > 0; switch (funct5) { case Funct5.lr: // lr命令 result = lsu.LrW(rd, rs1, ac, rl); break; case Funct5.sc: // sc命令 result = lsu.ScW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_swap: // swap命令 result = lsu.AmoSwapW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_add: // add命令 result = lsu.AmoAddW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_xor: // xor命令 result = lsu.AmoXorW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_and: // and命令 result = lsu.AmoAndW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_or: // or命令 result = lsu.AmoOrW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_min: // min命令 result = lsu.AmoMinW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_max: // max命令 result = lsu.AmoMaxW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_minu: // minu命令 result = lsu.AmoMinuW(rd, rs1, rs2, ac, rl); break; case Funct5.amo_maxu: // maxu命令 result = lsu.AmoMaxuW(rd, rs1, rs2, ac, rl); break; } } return(result); }