private RvcPayload DecodeCSS(IEnumerable <byte> rvcCoding) { var payload = new RvcPayload(rvcCoding); var immediate = 0; int buffer = rvcCoding.ElementAt(1); buffer <<= 8; buffer |= rvcCoding.First(); var opCode = buffer & 0x03; // Read RS2 buffer >>= 2; var rs2 = buffer & 0x1F; // Immediates buffer >>= 5; immediate = buffer & 0x3F; // F3 buffer >>= 6; var f3 = buffer & 0x7; payload.LoadCSS(opCode, rs2, immediate, f3); return(payload); }
private RvcPayload DecodeCR(IEnumerable <byte> rvcCoding) { var payload = new RvcPayload(rvcCoding); int immediate; int buffer = rvcCoding.ElementAt(1); buffer <<= 8; buffer |= rvcCoding.First(); var opCode = buffer & 0x03; // rs2 buffer >>= 2; var rs2 = buffer & 0x1F; // rs1 buffer >>= 5; var rs1 = buffer & 0x1F; // funct 4 buffer >>= 5; var f4 = buffer & 0x0F; // f3 buffer >>= 1; var f3 = buffer & 0x07; payload.LoadCR(opCode, rs1, rs2, f4, f3); return(payload); }
public void ParseSrli(RvcPayload payload, InstructionPayload instructionPayload) { // // C.SRLI is a CB-format instruction that performs a logical right shift of the value in register rd ′ // then writes the result to rd ′. The shift amount is encoded in the shamt field.For RV128C, a shift // amount of zero is used to encode a shift of 64.Furthermore, the shift amount is sign - extended for // RV128C, and so the legal shift amounts are 1–31, 64, and 96–127.C.SRLI expands into srli rd ′, // rd ′, shamt[5:0], except for RV128C with shamt = 0, which expands to srli rd ′, rd ′, 64. // // For RV32C, shamt[5] must be zero; the code points with shamt[5]=1 are reserved for custom // extensions.For RV32C and RV64C, the shift amount must be non - zero; the code points with // shamt = 0 are HINTs. Logger.Info("Parsing C.SRLI"); if ((payload.Immediate & 0x20) == 0x20) { throw new RvcFormatException("Bit 5 for the RV32C C.SRLI must be zero"); } // SRLI rd`,rd`,shamt[5:0] // srli rd rs1 31..26=0 shamt 14..12=5 6..2=0x04 1..0=3 instructionPayload.Funct3 = 5; instructionPayload.Rs1 = payload.Rs1; instructionPayload.Rd = payload.Rd; instructionPayload.SignedImmediate = payload.Immediate; }
private RvcPayload DecodeCB_Branch(IEnumerable <byte> rvcCoding) { var payload = new RvcPayload(rvcCoding); int immediate; int buffer = rvcCoding.ElementAt(1); buffer <<= 8; buffer |= rvcCoding.First(); var opCode = buffer & 0x03; // Imm 1 buffer >>= 2; immediate = buffer & 0x1F; // Rs1' buffer >>= 5; var rs1c = buffer & 0x7; // Imm 2 buffer >>= 3; var imm2 = buffer & 0x07; immediate |= (imm2 << 5); // f3 buffer >>= 3; var f3 = buffer & 0x07; payload.LoadCB_Branch(opCode, immediate, rs1c, f3); return(payload); }
public void ParseLui(RvcPayload payload, InstructionPayload instructionPayload) { // // C.LUI loads the non-zero 6-bit immediate field into bits 17–12 of the destination register, clears the // bottom 12 bits, and sign-extends bit 17 into all higher bits of the destination.C.LUI expands into // lui rd, nzimm[17:12].C.LUI is only valid when rd̸ = { x0, x2 }, and when the immediate is not // equal to zero. The code points with nzimm = 0 are reserved; the remaining code points with rd = x0 // are HINTs; and the remaining code points with rd = x2 correspond to the C.ADDI16SP instruction. // Logger.Info("Parsing C.LUI"); // nzimm[17...12] = payload.immediate if (payload.Rd == 0 || payload.Rd == 2) { throw new RvcFormatException("C.LUI does not accept RD=0 or RD=2"); } instructionPayload.Rd = payload.Rd; uint uimmediate = Convert.ToUInt32(payload.Immediate << 12); // Expand Bit 17 to the higher ones (31....17) uint bitmask = 0xFFFFC000; uint b17 = 0x020000; if ((uimmediate & b17) == b17) { uimmediate |= bitmask; } instructionPayload.UnsignedImmediate = uimmediate; }
private RvcPayload DecodeCIW(IEnumerable <byte> rvcCoding) { var payload = new RvcPayload(rvcCoding); int immediate; int buffer = rvcCoding.ElementAt(1); buffer <<= 8; buffer |= rvcCoding.First(); var opCode = buffer & 0x03; // rd' buffer >>= 2; var rdc = buffer & 0x07; // immm buffer >>= 3; immediate = 0xFFFF; // f3 buffer >>= 8; var f3 = buffer & 0x07; payload.LoadCIW(opCode, rdc, immediate, f3); return(payload); }
public void ParseJal(RvcPayload payload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.JAL"); instructionPayload.Rd = 1; instructionPayload.SignedImmediate = DecodeJalOffset(payload.Immediate); }
private RvcPayload DecodeCI(IEnumerable <byte> rvcCoding) { var payload = new RvcPayload(rvcCoding); var immediate = 0; int buffer = rvcCoding.ElementAt(1); buffer <<= 8; buffer |= rvcCoding.First(); // Read the opcode var opCode = buffer & 0x3; // Read the Immediate coding Bit 2..6 buffer >>= 2; immediate = buffer & 0x1F; // Read the rd register buffer >>= 5; var rd = buffer & 0x1F; // Read the imm. Bit 12 buffer >>= 5; var imm12 = (buffer & 0x01) << 5; immediate |= imm12; // read F3 buffer >>= 1; var f3 = buffer & 0x7; payload.LoadCI(opCode, immediate, rd, f3); return(payload); }
public void ParseCaGeneric(RvcPayload payload, InstructionPayload instructionPayload) { // // These instructions use the CA format. // // C.AND computes the bitwise AND of the values in registers rd ′ and rs2 ′, then writes the result to // register rd ′. C.AND expands into and rd ′, rd ′, rs2 ′. // // C.OR computes the bitwise OR of the values in registers rd ′ and rs2 ′, then writes the result to // register rd ′. C.OR expands into or rd ′, rd ′, rs2 ′. // // C.XOR computes the bitwise XOR of the values in registers rd ′ and rs2 ′, then writes the result to // register rd ′. C.XOR expands into xor rd ′, rd ′, rs2 ′. // // C.SUB subtracts the value in register rs2 ′ from the value in register rd ′, then writes the result to // register rd ′. C.SUB expands into sub rd ′, rd ′, rs2 ′. // add rd rs1 rs2 31..25 = 0 14..12 = 0 6..2 = 0x0C 1..0 = 3 // sub rd rs1 rs2 31..25 = 32 14..12 = 0 6..2 = 0x0C 1..0 = 3 // sll rd rs1 rs2 31..25 = 0 14..12 = 1 6..2 = 0x0C 1..0 = 3 // slt rd rs1 rs2 31..25 = 0 14..12 = 2 6..2 = 0x0C 1..0 = 3 // sltu rd rs1 rs2 31..25 = 0 14..12 = 3 6..2 = 0x0C 1..0 = 3 // xor rd rs1 rs2 31..25 = 0 14..12 = 4 6..2 = 0x0C 1..0 = 3 // srl rd rs1 rs2 31..25 = 0 14..12 = 5 6..2 = 0x0C 1..0 = 3 // sra rd rs1 rs2 31..25 = 32 14..12 = 5 6..2 = 0x0C 1..0 = 3 // or rd rs1 rs2 31..25 = 0 14..12 = 6 6..2 = 0x0C 1..0 = 3 // and rd rs1 rs2 31..25 = 0 14..12 = 7 6..2 = 0x0C 1..0 = 3 Logger.Info("Parsing C.SUB / C.XOR / C.OR / C.AND"); instructionPayload.Rs1 = payload.Rs1; instructionPayload.Rs2 = payload.Rs2; instructionPayload.Rd = payload.Rd; if (payload.CAMode == 0) { // C.SUB // f3 = 0 instructionPayload.Funct7 = 0x32; } if (payload.CAMode == 1) { // C.XOR instructionPayload.Funct3 = 4; } if (payload.CAMode == 2) { // C.OR instructionPayload.Funct3 = 6; } if (payload.CAMode == 3) { // C.AND instructionPayload.Funct3 = 7; } }
public void ParseSd(RvcPayload rvcPayload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.SD"); instructionPayload.Funct3 = 3; instructionPayload.Rs1 = rvcPayload.Rs1; instructionPayload.Rs2 = rvcPayload.Rs2; instructionPayload.SignedImmediate = DecodeLoadStoreOffset(rvcPayload.Immediate); }
public void ParseSlli(RvcPayload rvcPayload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.SLLI"); // slli rd rs1 31..26=0 shamt 14..12=1 6..2=0x04 1..0=3 instructionPayload.Rd = rvcPayload.Rd; instructionPayload.Rs1 = rvcPayload.Rs1; instructionPayload.Funct3 = 1; instructionPayload.SignedImmediate = rvcPayload.Immediate; }
public void ParseLdSp(RvcPayload rvcPayload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.LDSP"); // ld rd rs1 imm12 14..12=3 6..2=0x00 1..0=3 instructionPayload.Rd = rvcPayload.Rd; instructionPayload.Rs1 = 2; instructionPayload.Funct3 = 3; instructionPayload.SignedImmediate = DecodeLoadStoreSpOffset(rvcPayload.Immediate); }
public void ParseLd(RvcPayload rvcPayload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.LD"); // rs1 // rd // Offset : 5 4 3 7 6 (scaled by 8 (3 2 1 0)) instructionPayload.Funct3 = 3; instructionPayload.Rs1 = rvcPayload.Rs1; instructionPayload.Rd = rvcPayload.Rd; instructionPayload.SignedImmediate = DecodeLoadStoreOffset(rvcPayload.Immediate); }
public void ParseSdSp(RvcPayload rvcPayload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.SDSP"); // sd imm12hi rs1 rs2 imm12lo 14..12=3 6..2=0x08 1..0=3 instructionPayload.Rd = rvcPayload.Rd; instructionPayload.Rs1 = 2; instructionPayload.Rs2 = rvcPayload.Rs2; instructionPayload.Funct3 = 3; instructionPayload.SignedImmediate = DecodeLoadStoreSpOffset(rvcPayload.Immediate); }
public void ParseSlli(RvcPayload rvcPayload, InstructionPayload instructionPayload) { // C.SLLI is a CI-format instruction that performs a logical left shift of the value in register rd then // writes the result to rd.The shift amount is encoded in the shamt field. Logger.Info("Parsing C.SLLI"); instructionPayload.Rs1 = rvcPayload.Rs1; instructionPayload.Rd = rvcPayload.Rd; instructionPayload.Funct3 = 1; // The type decoder automatically generated the correct order instructionPayload.SignedImmediate = rvcPayload.Immediate; }
public void ParseAddiW(RvcPayload rvcPayload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.AddiW"); // addiw rd rs1 imm12 14..12=0 6..2=0x06 1..0=3 instructionPayload.Rd = rvcPayload.Rd; instructionPayload.Rs1 = rvcPayload.Rs1; var immediate = MathHelper.GetSignedInteger(rvcPayload.Immediate, 5); instructionPayload.SignedImmediate = immediate; }
public void ParseAddi16Sp(RvcPayload payload, InstructionPayload instructionPayload) { // // C.ADDI16SP shares the opcode with C.LUI, but has a destination field of x2. C.ADDI16SP adds // the non-zero sign - extended 6 - bit immediate to the value in the stack pointer(sp = x2), where the // immediate is scaled to represent multiples of 16 in the range(-512,496). C.ADDI16SP is used // to adjust the stack pointer in procedure prologues and epilogues. It expands into addi x2, x2, // nzimm[9:4].C.ADDI16SP is only valid when nzimm̸ = 0; the code point with nzimm = 0 is reserved. // Logger.Info("Parsing C.ADDI16SP"); instructionPayload.Rd = 2; instructionPayload.Rs1 = 2; // b5 int buffer = payload.Immediate; int immediate = buffer & 0x01; immediate <<= 5; // 8 7 buffer >>= 1; int b87 = buffer & 0x03; b87 <<= 7; immediate |= b87; // 6 buffer >>= 2; int b6 = buffer & 0x01; b6 <<= 6; immediate |= b6; // 4 buffer >>= 1; int b4 = buffer & 0x01; b4 <<= 4; immediate |= b4; // 9 buffer >>= 1; int b9 = buffer & 0x01; b9 <<= 9; immediate |= b9; instructionPayload.SignedImmediate = immediate; }
public void ParseAddAndMv(RvcPayload payload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.MV / C.ADD"); instructionPayload.Rd = payload.Rd; instructionPayload.Rs2 = payload.Rs2; // F4 == 9 => C.ADD // F4 == 8 => C.MV und RS1 = x0 if (payload.Funct4 == 9) { instructionPayload.Rs1 = payload.Rd; } }
public void ParseAddi(RvcPayload payload, InstructionPayload instructionPayload) { // // C.ADDI adds the non-zero sign-extended 6-bit immediate to the value in register rd then writes // the result to rd. C.ADDI expands into addi rd, rd, nzimm[5:0].C.ADDI is only valid when // rd̸ = x0 and nzimm̸ = 0.The code points with rd = x0 encode the C.NOP instruction; the remaining // code points with nzimm = 0 encode HINTs. // Logger.Info("Parsing C.ADDI"); instructionPayload.Rd = payload.Rd; instructionPayload.Rs1 = payload.Rs1; instructionPayload.SignedImmediate = payload.Immediate; // non-zero immediate. }
public void ParseBeqzAndBnez(RvcPayload payload, InstructionPayload instructionPayload, bool forEqual) { Logger.Info("Parsing C.BEQZ / C.BNEZ"); if (forEqual) { instructionPayload.Funct3 = 0; } else { instructionPayload.Funct3 = 1; } instructionPayload.Rs1 = payload.Rs1; instructionPayload.SignedImmediate = DecodeCbOffset(payload.Immediate); }
public void ParseAndi(RvcPayload payload, InstructionPayload instructionPayload) { // // C.ANDI is a CB-format instruction that computes the bitwise AND of the value in register rd ′ and // the sign-extended 6 - bit immediate, then writes the result to rd ′. C.ANDI expands to andi rd ′, // rd ′, imm[5:0]. // Logger.Info("Parsing C.ANDI"); instructionPayload.Funct3 = 7; instructionPayload.Rs1 = payload.Rs1; instructionPayload.Rd = payload.Rd; // Signed 6 Bit imm instructionPayload.SignedImmediate = MathHelper.GetSignedInteger(payload.Immediate, 5); }
public void ParseJrAndJalr(RvcPayload rvcPayload, InstructionPayload instructionPayload) { // // F4 = 8 // C.JR (jump register) performs an unconditional control transfer to the address in register rs1. // C.JR expands to jalr x0, 0(rs1).C.JR is only valid when rs1̸ = x0; the code point with rs1 = x0 // is reserved. // // F4 = 9 // C.JALR (jump and link register) performs the same operation as C.JR, but additionally writes the // address of the instruction following the jump(pc + 2) to the link register, x1. C.JALR expands to // jalr x1, 0(rs1).C.JALR is only valid when rs1̸ = x0; the code point with rs1 = x0 corresponds // to the C.EBREAK instruction. // // Logger.Info("Parsing C.JR / C.JALR with F4 = {f4:X}", rvcPayload.Funct4); var f4 = rvcPayload.Funct4; if (f4 == 8) { // C.JR if (rvcPayload.Rs1 == 0) { throw new RvcFormatException("Invalid C.JR coding. Rs1 cannot be 0"); } instructionPayload.Rs1 = rvcPayload.Rs1; } if (f4 == 9) { // C.JALR if (rvcPayload.Rs1 == 0) { throw new RvcFormatException("Invalid C.JALR coding. Rs1 cannot be 0"); } instructionPayload.Rd = 1; instructionPayload.Rs1 = rvcPayload.Rs1; } // RvcFormatException }
public void ParseSw(RvcPayload rvcPayload, InstructionPayload instructionPayload) { // // C.SW stores a 32-bit value in register rs2 ′ to memory. It computes an effective address by adding // the zero-extended offset, scaled by 4, to the base address in register rs1 ′. It expands to sw rs2 ′, // offset[6:2](rs1 ′). // Logger.Info("Parsing C.SP"); instructionPayload.Funct3 = 2; instructionPayload.Rs2 = rvcPayload.Rs2; // The source instructionPayload.Rs1 = rvcPayload.Rs1; // The register pointing to the memory address int immediate = DecodeLoadStoreW(rvcPayload.Immediate); instructionPayload.SignedImmediate = immediate; }
public void ParseLw(RvcPayload rvcPayload, InstructionPayload instructionPayload) { // // C.LW loads a 32-bit value from memory into register rd ′. It computes an effective address by // adding the zero - extended offset, scaled by 4, to the base address in register rs1 ′. It expands to lw // rd ′, offset[6:2](rs1 ′). // Logger.Info("Parsing C.LW"); instructionPayload.Rd = rvcPayload.Rd; instructionPayload.Rs1 = rvcPayload.Rs1; instructionPayload.Funct3 = 2; int immediate = DecodeLoadStoreW(rvcPayload.Immediate); instructionPayload.SignedImmediate = immediate; }
public void ParseSwSp(RvcPayload rvcPayload, InstructionPayload instructionPayload) { // // C.SWSP stores a 32-bit value in register rs2 to memory. It computes an effective address by // adding the zero - extended offset, scaled by 4, to the stack pointer, x2. It expands to sw rs2, // offset[7:2](x2). // // Immediate : [5] [4] [3] [2] [7] [6] Logger.Info("Parsing C.SWSP"); instructionPayload.Funct3 = 2; instructionPayload.Rs2 = rvcPayload.Rs2; // The source instructionPayload.Rs1 = 2; // The register pointing to the memory address int immediate = DecodeLoadStoreSp(rvcPayload.Immediate); instructionPayload.SignedImmediate = immediate; }
public void ParseAddi4Spn(RvcPayload payload, InstructionPayload instructionPayload) { // C.ADDI4SPN is a CIW-format instruction that adds a zero-extended non-zero immediate, scaled // by 4, to the stack pointer, x2, and writes the result to rd ′. This instruction is used to generate // pointers to stack-allocated variables, and expands to addi rd ′, x2, nzuimm[9:2].C.ADDI4SPN // is only valid when nzuimm̸ = 0; the code points with nzuimm = 0 are reserved. Logger.Info("Parsing C.ADDI4SPN"); // nzuimm 5 4 9 8 7 6 2 3 instructionPayload.Rs1 = 2; instructionPayload.Rd = payload.Rd; instructionPayload.Funct3 = 0; // 3 int buffer = payload.Immediate; int immediate = buffer & 0x01; int current; immediate <<= 3; // 2 buffer >>= 1; current = buffer & 0x01; current <<= 2; immediate |= current; // 9 8 7 6 buffer >>= 1; current = buffer & 0x0F; current <<= 6; immediate |= current; // 5 4 buffer >>= 4; current = buffer & 0x03; current <<= 4; immediate |= current; instructionPayload.SignedImmediate = immediate; }
public void ParseAddWSubW(RvcPayload rvcPayload, InstructionPayload instructionPayload) { Logger.Info("Parsing C.AddW / C.SubW"); // addw rd rs1 rs2 31..25 = 0 14..12 = 0 6..2 = 0x0E 1..0 = 3 // subw rd rs1 rs2 31..25 = 32 14..12 = 0 6..2 = 0x0E 1..0 = 3 instructionPayload.Funct3 = 0; // C.SUBW if (rvcPayload.CAMode == 0) { instructionPayload.Funct7 = 0x32; } instructionPayload.Rs1 = rvcPayload.Rs1; instructionPayload.Rs2 = rvcPayload.Rs2; instructionPayload.Rd = rvcPayload.Rd; }
public RvcPayload Decode(IEnumerable <byte> rvcCoding) { RvcPayload payload = null; if (rvcCoding == null) { throw new ArgumentNullException("rvcCoding"); } // Start the parsing with the the opcode and the F3 var firstByte = rvcCoding.First(); var secondByte = rvcCoding.ElementAt(1); var opCode = firstByte & 0x03; var f3 = secondByte >> 5; Logger.Info("RVC = {0}, OpCode = {0:X}, F3 = {1:X}", BitConverter.ToString(rvcCoding.ToArray(), 0), opCode, f3); if (opCode == 0x00) { payload = DecodeGroup00(rvcCoding, opCode, f3); } if (opCode == 0x01) { payload = DecodeGroup01(rvcCoding, opCode, f3); } if (opCode == 0x02) { payload = DecodeGroup10(rvcCoding, opCode, f3); } // Something went wrong.. raise an exception! if (payload == null) { var rvcError = String.Format("Could not decode coding {0} on {1}", BitConverter.ToString(rvcCoding.ToArray(), 0), architecture); Logger.Error(rvcError); throw new RvcFormatException(rvcError); } return(payload); }
public void ParseSrai(RvcPayload payload, InstructionPayload instructionPayload) { // // C.SRAI is defined analogously to C.SRLI, but instead performs an arithmetic right shift. C.SRAI // expands to srai rd ′, rd ′, shamt[5:0]. // // srai rd rs1 31..26 = 16 shamt 14..12 = 5 6..2 = 0x04 1..0 = 3 Logger.Info("Parsing C.SRAI"); if ((payload.Immediate & 0x20) == 0x20) { throw new RvcFormatException("Bit 5 for the RV32C C.SRAI must be zero"); } instructionPayload.Funct3 = 5; instructionPayload.Rs1 = payload.Rs1; instructionPayload.Rd = payload.Rd; instructionPayload.SignedImmediate = payload.Immediate | 0x400; }
public void ParseLwSp(RvcPayload rvcPayload, InstructionPayload instructionPayload) { // // C.LWSP loads a 32-bit value from memory into register rd. It computes an effective address // by adding the zero-extended offset, scaled by 4, to the stack pointer, x2. It expands to lw rd, // offset[7:2](x2).C.LWSP is only valid when rd̸ = x0; the code points with rd = x0 are reserved. // // 15...13 12 11..7 6 ... 2 1..0 // C.LWSP offset[5] dest̸=0 offset[4:2|7:6] C2 // // Immediate : [5] [4] [3] [2] [7] [6] Logger.Info("Parsing C.LWSP"); instructionPayload.Rd = rvcPayload.Rd; instructionPayload.Funct3 = 2; instructionPayload.Rs1 = 2; int immediate = DecodeLoadStoreSp(rvcPayload.Immediate); instructionPayload.SignedImmediate = immediate; }