/// <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];
            Funct7   funct7 = (Funct7)(ins[5] + (ins[6] << 6));
            RV32_Mac alu;


            if (opcode == Opcode.miscOp && funct7 == Funct7.mul_div)   // Op系命令(算術論理演算)
            {
                alu = (RV32_Mac)Decoder.Alu(typeof(RV32_Mac));
                switch (funct3)
                {
                case Funct3.mul:     // mul命令
                    result = alu.Mul(rd, rs1, rs2);
                    break;

                case Funct3.mulh:     // mulh命令
                    result = alu.Mulh(rd, rs1, rs2);
                    break;

                case Funct3.mulhsu:     // mulhsu命令
                    result = alu.Mulhsu(rd, rs1, rs2);
                    break;

                case Funct3.mulhu:     // mulhu命令
                    result = alu.Mulhu(rd, rs1, rs2);
                    break;

                case Funct3.div:     // div命令
                    result = alu.Div(rd, rs1, rs2);
                    break;

                case Funct3.divu:     // divu命令
                    result = alu.Divu(rd, rs1, rs2);
                    break;

                case Funct3.rem:     // rem命令
                    result = alu.Rem(rd, rs1, rs2);
                    break;

                case Funct3.remu:     // remu命令
                    result = alu.Remu(rd, rs1, rs2);
                    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);
            }

            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);
            }

            Register rd               = (Register)ins[1],
                     rs1              = (Register)ins[3],
                     rs2              = (Register)ins[4];
            Opcode          opcode    = (Opcode)ins[0];
            Funct3          funct3    = (Funct3)ins[2];
            Funct7          funct7    = (Funct7)(ins[5] | (ins[6] << 6));
            Int32           immediate = 0;
            RV32_IntegerAlu alu;
            RV32_IntegerLsu lsu;

            switch (opcode)
            {
            case Opcode.lui:     // lui命令
                immediate = GetImmediate('U', ins);
                alu       = (RV32_IntegerAlu)Decoder.Alu(typeof(RV32_IntegerAlu));
                result    = alu.Lui(rd, immediate);
                break;


            case Opcode.auipc:     // auipc命令
                immediate = GetImmediate('U', ins);
                alu       = (RV32_IntegerAlu)Decoder.Alu(typeof(RV32_IntegerAlu));
                result    = alu.Auipc(rd, immediate);
                break;

            case Opcode.jal:     // jal命令
                immediate = GetImmediate('J', ins);
                result    = Decoder.Reg.Jal(rd, immediate);
                break;

            case Opcode.jalr:     // jalr命令
                if (funct3 == Funct3.jalr)
                {
                    immediate = GetImmediate('I', ins);
                    result    = Decoder.Reg.Jalr(rd, rs1, immediate);
                }
                break;

            case Opcode.branch:     // Branch系命令
                immediate = GetImmediate('B', ins);
                switch (funct3)
                {
                case Funct3.beq:         // beq命令
                    result = Decoder.Reg.Beq(rs1, rs2, immediate);
                    break;

                case Funct3.bne:         // bne命令
                    result = Decoder.Reg.Bne(rs1, rs2, immediate);
                    break;

                case Funct3.blt:         // blt命令
                    result = Decoder.Reg.Blt(rs1, rs2, immediate);
                    break;

                case Funct3.bge:         // bge命令
                    result = Decoder.Reg.Bge(rs1, rs2, immediate);
                    break;

                case Funct3.bltu:         // bltu命令
                    result = Decoder.Reg.Bltu(rs1, rs2, immediate);
                    break;

                case Funct3.bgeu:         // bgeu命令
                    result = Decoder.Reg.Bgeu(rs1, rs2, immediate);
                    break;
                }
                break;

            case Opcode.load:     // Load系命令
                immediate = GetImmediate('I', ins);
                lsu       = (RV32_IntegerLsu)Decoder.Lsu(typeof(RV32_IntegerLsu));
                switch (funct3)
                {
                case Funct3.lb:         // lb命令
                    result = lsu.Lb(rd, rs1, immediate);
                    break;

                case Funct3.lh:         // lh命令
                    result = lsu.Lh(rd, rs1, immediate);
                    break;

                case Funct3.lw:         //010 lw命令
                    result = lsu.Lw(rd, rs1, immediate);
                    break;

                case Funct3.lbu:         //001 lbu命令
                    result = lsu.Lbu(rd, rs1, immediate);
                    break;

                case Funct3.lhu:         //101 lhu命令
                    result = lsu.Lhu(rd, rs1, immediate);
                    break;
                }
                break;

            case Opcode.store:     // Store系命令
                immediate = GetImmediate('S', ins);
                lsu       = (RV32_IntegerLsu)Decoder.Lsu(typeof(RV32_IntegerLsu));
                switch (funct3)
                {
                case Funct3.sb:         // sb命令
                    result = lsu.Sb(rs1, rs2, immediate);
                    break;

                case Funct3.sh:         // sh命令
                    result = lsu.Sh(rs1, rs2, immediate);
                    break;

                case Funct3.sw:         // sw命令
                    result = lsu.Sw(rs1, rs2, immediate);
                    break;
                }
                break;

            case Opcode.miscOpImm:     // Op-imm系命令(即値算術論理演算)
                alu = (RV32_IntegerAlu)Decoder.Alu(typeof(RV32_IntegerAlu));
                switch (funct3)
                {
                case Funct3.addi:         // addi命令
                    immediate = GetImmediate('I', ins);
                    result    = alu.Addi(rd, rs1, immediate);
                    break;

                case Funct3.xori:         // xori命令
                    immediate = GetImmediate('I', ins);
                    result    = alu.Xori(rd, rs1, immediate);
                    break;

                case Funct3.ori:         // ori命令
                    immediate = GetImmediate('I', ins);
                    result    = alu.Ori(rd, rs1, immediate);
                    break;

                case Funct3.andi:         // andi命令
                    immediate = GetImmediate('I', ins);
                    result    = alu.Andi(rd, rs1, immediate);
                    break;

                case Funct3.slti:         // slti命令
                    immediate = GetImmediate('I', ins);
                    result    = alu.Slti(rd, rs1, immediate);
                    break;

                case Funct3.sltiu:         //110 sltiu命令
                    immediate = GetImmediate('I', ins);
                    result    = alu.Sltiu(rd, rs1, immediate);
                    break;

                case Funct3.slli when funct7 == Funct7.slli:         // slli命令
                    result = alu.Slli(rd, rs1, (Int32)ins[4]);
                    break;

                case Funct3.srli_srai when funct7 == Funct7.srli:         // srli命令
                    result = alu.Srli(rd, rs1, (Int32)ins[4]);
                    break;

                case Funct3.srli_srai when funct7 == Funct7.srai:         // srai命令
                    result = alu.Srai(rd, rs1, (Int32)ins[4]);
                    break;
                }
                break;

            case Opcode.miscOp:     // Op系命令(算術論理演算)
                alu = (RV32_IntegerAlu)Decoder.Alu(typeof(RV32_IntegerAlu));
                switch (((UInt16)funct3 | ((UInt16)funct7 << 3)))
                {
                case (UInt16)Funct3.add_sub | ((UInt16)Funct7.add << 3):         // add命令
                    result = alu.Add(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.add_sub | ((UInt16)Funct7.sub << 3):         // sub命令
                    result = alu.Sub(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.xor | ((UInt16)Funct7.xor << 3):         // xor命令
                    result = alu.Xor(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.or | ((UInt16)Funct7.or << 3):         // or命令
                    result = alu.Or(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.and | ((UInt16)Funct7.and << 3):         // and命令
                    result = alu.And(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.slt | ((UInt16)Funct7.slt << 3):         // slt命令
                    result = alu.Slt(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.sltu | ((UInt16)Funct7.sltu << 3):         // sltu命令
                    result = alu.Sltu(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.sll | ((UInt16)Funct7.sll << 3):         // sll命令
                    result = alu.Sll(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.srl_sra | ((UInt16)Funct7.srl << 3):         // srl命令
                    result = alu.Srl(rd, rs1, rs2);
                    break;

                case (UInt16)Funct3.srl_sra | ((UInt16)Funct7.sra << 3):         // sra命令
                    result = alu.Sra(rd, rs1, rs2);
                    break;
                }
                break;

            case Opcode.miscMem:     // 同期命令
                switch (funct3)
                {
                case Funct3.fence:         // fence命令
                    result = Decoder.Reg.Fence((byte)(((ins[5] & 0x7) << 5) | ins[4]));
                    break;

                case Funct3.fenceI:         // fence.i命令
                    result = Decoder.Reg.FenceI();
                    break;
                }
                break;

            case Opcode.system:     // システム命令
                switch (funct3)
                {
                case Funct3.privilege:         // 特権命令
                    if (rd == 0 && funct7 == Funct7.sfenceVma)
                    {
                        result = Decoder.Reg.SfenceVma(rs1, rs2);
                    }
                    else if (rd == 0 && rs1 == 0)
                    {
                        Funct12 funct12 = (Funct12)(ins[4] | (ins[5] << 5) | (ins[6] << 11));;
                        switch (funct12)
                        {
                        case Funct12.ecall:
                            result = Decoder.Reg.Ecall();
                            break;

                        case Funct12.ebreak:
                            result = Decoder.Reg.Ebreak();
                            break;

                        case Funct12.mret:
                            result = Decoder.Reg.Mret();
                            break;

                        case Funct12.sret:
                            result = Decoder.Reg.Sret();
                            break;

                        case Funct12.uret:
                            result = Decoder.Reg.Uret();
                            break;

                        case Funct12.wfi:
                            result = Decoder.Reg.Wfi();
                            break;
                        }
                    }
                    break;

                case Funct3.csrrw:         // csrrw命令
                    immediate = (GetImmediate('I', ins) & 0xfff);
                    result    = Decoder.Reg.Csrrw(rd, rs1, (CSR)immediate);
                    break;

                case Funct3.csrrs:         // csrrs命令
                    immediate = (GetImmediate('I', ins) & 0xfff);
                    result    = Decoder.Reg.Csrrs(rd, rs1, (CSR)immediate);
                    break;

                case Funct3.csrrc:         // csrrc命令
                    immediate = (GetImmediate('I', ins) & 0xfff);
                    result    = Decoder.Reg.Csrrc(rd, rs1, (CSR)immediate);
                    break;

                case Funct3.csrrwi:         // csrrwi命令
                    immediate = (GetImmediate('I', ins) & 0xfff);
                    result    = Decoder.Reg.Csrrwi(rd, (byte)ins[3], (CSR)immediate);
                    break;

                case Funct3.csrrsi:         // csrrsi命令
                    immediate = (GetImmediate('I', ins) & 0xfff);
                    result    = Decoder.Reg.Csrrsi(rd, (byte)ins[3], (CSR)immediate);
                    break;

                case Funct3.csrrci:         // csrrci命令
                    immediate = (GetImmediate('I', ins) & 0xfff);
                    result    = Decoder.Reg.Csrrci(rd, (byte)ins[3], (CSR)immediate);
                    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);
        }