1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using Antmicro.Renode.Core; 8 using Antmicro.Renode.Logging; 9 using Antmicro.Renode.Peripherals.Timers; 10 using Antmicro.Renode.Utilities; 11 using Endianess = ELFSharp.ELF.Endianess; 12 13 namespace Antmicro.Renode.Peripherals.CPU 14 { 15 public class CV32E40P : RiscV32 16 { CV32E40P(IMachine machine, IRiscVTimeProvider timeProvider = null, uint hartId = 0, [NameAlias(R)] PrivilegedArchitecture privilegedArchitecture = PrivilegedArchitecture.Priv1_11, Endianess endianness = Endianess.LittleEndian, string cpuType = R)17 public CV32E40P(IMachine machine, IRiscVTimeProvider timeProvider = null, uint hartId = 0, [NameAlias("privilegeArchitecture")] PrivilegedArchitecture privilegedArchitecture = PrivilegedArchitecture.Priv1_11, Endianess endianness = Endianess.LittleEndian, string cpuType = "rv32imfc_zicsr_zifencei") 18 : base(machine, cpuType, timeProvider, hartId, privilegedArchitecture, endianness, allowUnalignedAccesses : true) 19 { 20 // enable all interrupt sources 21 MIE = 0xffffffff; 22 23 RegisterCSR((ulong)CustomCSR.PerformanceCounterMode, () => LogUnhandledCSRRead("PerformanceCounterMode"), val => LogUnhandledCSRWrite("PerformanceCounterMode", val)); 24 RegisterCSR((ulong)CustomCSR.StackCheckEnable , () => LogUnhandledCSRRead("StackCheckEnable") , val => LogUnhandledCSRWrite("StackCheckEnable", val)); 25 RegisterCSR((ulong)CustomCSR.StackBase , () => LogUnhandledCSRRead("StackBase") , val => LogUnhandledCSRWrite("StackBase", val)); 26 RegisterCSR((ulong)CustomCSR.StackEnd , () => LogUnhandledCSRRead("StackEnd") , val => LogUnhandledCSRWrite("StackEnd", val)); 27 RegisterCSR((ulong)CustomCSR.HardwareLoop0Start , () => LogUnhandledCSRRead("HardwareLoop0Start") , val => LogUnhandledCSRWrite("HardwareLoop0Start", val)); 28 RegisterCSR((ulong)CustomCSR.HardwareLoop0End , () => LogUnhandledCSRRead("HardwareLoop0End") , val => LogUnhandledCSRWrite("HardwareLoop0End", val)); 29 RegisterCSR((ulong)CustomCSR.HardwareLoop0Counter , () => LogUnhandledCSRRead("HardwareLoop0Counter") , val => LogUnhandledCSRWrite("HardwareLoop0Counter", val)); 30 RegisterCSR((ulong)CustomCSR.HardwareLoop1Start , () => LogUnhandledCSRRead("HardwareLoop1Start") , val => LogUnhandledCSRWrite("HardwareLoop1Start", val)); 31 RegisterCSR((ulong)CustomCSR.HardwareLoop1End , () => LogUnhandledCSRRead("HardwareLoop1End") , val => LogUnhandledCSRWrite("HardwareLoop1End", val)); 32 RegisterCSR((ulong)CustomCSR.HardwareLoop1Counter , () => LogUnhandledCSRRead("HardwareLoop1Counter") , val => LogUnhandledCSRWrite("HardwareLoop1Counter", val)); 33 34 InstallCustomInstruction(pattern: "FFFFFFFFFFFFBBBBB000DDDDD0001011", handler: opcode => LoadRegisterImmediate(opcode, Width.Byte, BitExtension.Sign, "p.lb rD, Imm(rs1!)")); 35 InstallCustomInstruction(pattern: "FFFFFFFFFFFFBBBBB100DDDDD0001011", handler: opcode => LoadRegisterImmediate(opcode, Width.Byte, BitExtension.Zero, "p.lbu rD, Imm(rs1!)")); 36 InstallCustomInstruction(pattern: "FFFFFFFFFFFFBBBBB001DDDDD0001011", handler: opcode => LoadRegisterImmediate(opcode, Width.HalfWord, BitExtension.Sign, "p.lh rD, Imm(rs1!)")); 37 InstallCustomInstruction(pattern: "FFFFFFFFFFFFBBBBB101DDDDD0001011", handler: opcode => LoadRegisterImmediate(opcode, Width.HalfWord, BitExtension.Zero, "p.lhu rD, Imm(rs1!)")); 38 InstallCustomInstruction(pattern: "FFFFFFFFFFFFBBBBB010DDDDD0001011", handler: opcode => LoadRegisterImmediate(opcode, Width.Word, BitExtension.Zero, "p.lw rD, Imm(rs1!)")); 39 InstallCustomInstruction(pattern: "0000000FFFFFBBBBB111DDDDD0001011", handler: opcode => LoadRegisterRegister(opcode, Width.Byte, BitExtension.Sign, postIncrement: true, log: "p.lb rD, rs2(rs1!)")); 40 InstallCustomInstruction(pattern: "0100000FFFFFBBBBB111DDDDD0001011", handler: opcode => LoadRegisterRegister(opcode, Width.Byte, BitExtension.Zero, postIncrement: true, log: "p.lbu rD, rs2(rs1!)")); 41 InstallCustomInstruction(pattern: "0001000FFFFFBBBBB111DDDDD0001011", handler: opcode => LoadRegisterRegister(opcode, Width.HalfWord, BitExtension.Sign, postIncrement: true, log: "p.lh rD, rs2(rs1!)")); 42 InstallCustomInstruction(pattern: "0101000FFFFFBBBBB111DDDDD0001011", handler: opcode => LoadRegisterRegister(opcode, Width.HalfWord, BitExtension.Zero, postIncrement: true, log: "p.lhu rD, rs2(rs1!)")); 43 InstallCustomInstruction(pattern: "0010000FFFFFBBBBB111DDDDD0001011", handler: opcode => LoadRegisterRegister(opcode, Width.Word, BitExtension.Zero, postIncrement: true, log: "p.lw rD, rs2(rs1!)")); 44 InstallCustomInstruction(pattern: "0000000FFFFFBBBBB111DDDDD0000011", handler: opcode => LoadRegisterRegister(opcode, Width.Byte, BitExtension.Sign, "p.lb rD, rs2(rs1)")); 45 InstallCustomInstruction(pattern: "0100000FFFFFBBBBB111DDDDD0000011", handler: opcode => LoadRegisterRegister(opcode, Width.Byte, BitExtension.Zero, "p.lbu rD, rs2(rs1)")); 46 InstallCustomInstruction(pattern: "0001000FFFFFBBBBB111DDDDD0000011", handler: opcode => LoadRegisterRegister(opcode, Width.HalfWord, BitExtension.Sign, "p.lh rD, rs2(rs1)")); 47 InstallCustomInstruction(pattern: "0101000FFFFFBBBBB111DDDDD0000011", handler: opcode => LoadRegisterRegister(opcode, Width.HalfWord, BitExtension.Zero, "p.lhu rD, rs2(rs1)")); 48 InstallCustomInstruction(pattern: "0010000FFFFFBBBBB111DDDDD0000011", handler: opcode => LoadRegisterRegister(opcode, Width.Word, BitExtension.Zero, "p.lw rD, rs2(rs1)")); 49 InstallCustomInstruction(pattern: "FFFFFFFSSSSSBBBBB000FFFFF0101011", handler: opcode => StoreRegisterImmediate(opcode, Width.Byte, "p.sb rs2, Imm(rs1!)")); 50 InstallCustomInstruction(pattern: "FFFFFFFSSSSSBBBBB001FFFFF0101011", handler: opcode => StoreRegisterImmediate(opcode, Width.HalfWord, "p.sh rs2, Imm(rs1!)")); 51 InstallCustomInstruction(pattern: "FFFFFFFSSSSSBBBBB010FFFFF0101011", handler: opcode => StoreRegisterImmediate(opcode, Width.Word, "p.sw rs2, Imm(rs1!)")); 52 InstallCustomInstruction(pattern: "0000000SSSSSBBBBB100FFFFF0101011", handler: opcode => StoreRegisterRegister(opcode, Width.Byte, postIncrement: true, log: "p.sb rs2, rs3(rs1!)")); 53 InstallCustomInstruction(pattern: "0000000SSSSSBBBBB101FFFFF0101011", handler: opcode => StoreRegisterRegister(opcode, Width.HalfWord, postIncrement: true, log: "p.sh rs2, rs3(rs1!)")); 54 InstallCustomInstruction(pattern: "0000000SSSSSBBBBB110FFFFF0101011", handler: opcode => StoreRegisterRegister(opcode, Width.Word, postIncrement: true, log: "p.sw rs2, rs3(rs1!)")); 55 InstallCustomInstruction(pattern: "0000000SSSSSBBBBB100FFFFF0100011", handler: opcode => StoreRegisterRegister(opcode, Width.Byte, "p.sb rs2, rs3(rs1)")); 56 InstallCustomInstruction(pattern: "0000000SSSSSBBBBB101FFFFF0100011", handler: opcode => StoreRegisterRegister(opcode, Width.HalfWord, "p.sh rs2, rs3(rs1)")); 57 InstallCustomInstruction(pattern: "0000000SSSSSBBBBB110FFFFF0100011", handler: opcode => StoreRegisterRegister(opcode, Width.Word, "p.sw rs2, rs3(rs1)")); 58 InstallCustomInstruction(pattern: "0000010RRRRRSSSSS100DDDDD0110011", handler: opcode => CompareRegisters(opcode, ComparisonType.Min, Sign.Signed, "p.min rD, rs1, rs2")); 59 InstallCustomInstruction(pattern: "0000010RRRRRSSSSS101DDDDD0110011", handler: opcode => CompareRegisters(opcode, ComparisonType.Min, Sign.Unsigned, "p.minu rD, rs1, rs2")); 60 InstallCustomInstruction(pattern: "0000010RRRRRSSSSS110DDDDD0110011", handler: opcode => CompareRegisters(opcode, ComparisonType.Max, Sign.Signed, "p.max rD, rs1, rs2")); 61 InstallCustomInstruction(pattern: "0000010RRRRRSSSSS111DDDDD0110011", handler: opcode => CompareRegisters(opcode, ComparisonType.Max, Sign.Unsigned, "p.maxu rD, rs1, rs2")); 62 InstallCustomInstruction(pattern: "11LLLLLLLLLLSSSSS000DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Extract, Width.Word, Sign.Signed, "p.extract rD, rs1, Is3, Is2")); 63 InstallCustomInstruction(pattern: "11LLLLLLLLLLSSSSS001DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Extract, Width.Word, Sign.Unsigned, "p.extractu rD, rs1, Is3, Is2")); 64 InstallCustomInstruction(pattern: "1000000LLLLLSSSSS000DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Register, Operation.Extract, Width.Word, Sign.Signed, "p.extractr rD, rs1, rs2")); 65 InstallCustomInstruction(pattern: "1000000LLLLLSSSSS001DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Register, Operation.Extract, Width.Word, Sign.Unsigned, "p.extractur rD, rs1, rs2")); 66 InstallCustomInstruction(pattern: "000100000000SSSSS100DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Extract, Width.HalfWord, Sign.Signed, "p.exths rD, rs1")); 67 InstallCustomInstruction(pattern: "000100000000SSSSS101DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Extract, Width.HalfWord, Sign.Unsigned, "p.exthz rD, rs1")); 68 InstallCustomInstruction(pattern: "000100000000SSSSS110DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Extract, Width.Byte, Sign.Signed, "p.extbs rD, rs1")); 69 InstallCustomInstruction(pattern: "000100000000SSSSS111DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Extract, Width.Byte, Sign.Unsigned, "p.extbz rD, rs1")); 70 InstallCustomInstruction(pattern: "11LLLLLLLLLLSSSSS010DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Insert, Width.Word, Sign.Unsigned, "p.insert rD, rs1, Is3, Is2")); 71 InstallCustomInstruction(pattern: "1000000LLLLLSSSSS010DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Register, Operation.Insert, Width.Word, Sign.Unsigned, "p.insertr rD, rs1, rs2")); 72 InstallCustomInstruction(pattern: "11LLLLLLLLLLSSSSS011DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Clear, Width.Word, Sign.Unsigned, "p.bclr rD, rs1, Is3, Is2")); 73 InstallCustomInstruction(pattern: "1000000LLLLLSSSSS011DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Register, Operation.Clear, Width.Word, Sign.Unsigned, "p.bclrr rD, rs1, rs2")); 74 InstallCustomInstruction(pattern: "11LLLLLLLLLLSSSSS100DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Immediate, Operation.Set, Width.Word, Sign.Unsigned, "p.bset rD, rs1, Is3, Is2")); 75 InstallCustomInstruction(pattern: "1000000LLLLLSSSSS100DDDDD0110011", handler: opcode => ManipulateBitsInRegister(opcode, Source.Register, Operation.Set, Width.Word, Sign.Unsigned, "p.bsetr rD, rs1, rs2")); 76 InstallCustomInstruction(pattern: "JJJJJJJIIIIISSSSS010JJJJJ1100011", handler: opcode => BranchIf(opcode, Equality.Equal, "p.beqimm rs1, Imm5, Imm12")); 77 InstallCustomInstruction(pattern: "JJJJJJJIIIIISSSSS011JJJJJ1100011", handler: opcode => BranchIf(opcode, Equality.NotEqual, "p.bneimm rs1, Imm5, Imm12")); 78 InstallCustomInstruction(pattern: "0100001RRRRRSSSSS001DDDDD0110011", handler: opcode => MultiplyAccumulate(opcode, operationAdd: false, log: "p.msu rD, rs1, rs2")); 79 InstallCustomInstruction(pattern: "0100001RRRRRSSSSS000DDDDD0110011", handler: opcode => MultiplyAccumulate(opcode, operationAdd: true, log: "p.mac rD, rs1, rs2")); 80 InstallCustomInstruction(pattern: "00---------------001-----1011011", handler: _ => LogUnsupported("p.macuN rD, rs1, rs2, Is3")); 81 InstallCustomInstruction(pattern: "00---------------110-----1011011", handler: _ => LogUnsupported("p.mac.zh.zl")); 82 InstallCustomInstruction(pattern: "00---------------100-----1011011", handler: _ => LogUnsupported("p.mac.zl.zl")); 83 InstallCustomInstruction(pattern: "00---------------111-----1011011", handler: _ => LogUnsupported("p.mac.zh.zh")); 84 InstallCustomInstruction(pattern: "00---------------101-----1011011", handler: _ => LogUnsupported("p.mac.zl.zh")); 85 InstallCustomInstruction(pattern: "01---------------100-----1011011", handler: _ => LogUnsupported("p.mac.zl.sl")); 86 InstallCustomInstruction(pattern: "------------000000000000-1111011", handler: _ => LogUnsupported("lp.starti L, uimmL")); 87 InstallCustomInstruction(pattern: "------------000000010000-1111011", handler: _ => LogUnsupported("lp.endi L, uimmL")); 88 InstallCustomInstruction(pattern: "00---------------010-----1011011", handler: _ => LogUnsupported("p.addN rD, rs1, rs2, Is3")); 89 InstallCustomInstruction(pattern: "1100000----------010-----1011011", handler: _ => LogUnsupported("p.adduNr rD, rs1, rs")); 90 InstallCustomInstruction(pattern: "-----------------1000000-1111011", handler: _ => LogUnsupported("lp.setup L, rs1, uimmL")); 91 InstallCustomInstruction(pattern: "-----------------1010000-1111011", handler: _ => LogUnsupported("lp.setupi L, uimmS, uimmL")); 92 InstallCustomInstruction(pattern: "000000000000-----0100000-1111011", handler: _ => LogUnsupported("lp.count L, rs1")); 93 InstallCustomInstruction(pattern: "00---------------011-----1011011", handler: _ => LogUnsupported("p.subN rD, rs1, rs2, Is3")); 94 InstallCustomInstruction(pattern: "10---------------011-----1011011", handler: _ => LogUnsupported("p.subuN rD, rs1, rs2, Is3")); 95 InstallCustomInstruction(pattern: "10---------------000-----1011011", handler: _ => LogUnsupported("p.mulsN rD, rs1, rs2, Is3")); 96 InstallCustomInstruction(pattern: "01---------------000-----1011011", handler: _ => LogUnsupported("p.mulhhuN rD, rs1, rs2, Is3")); 97 InstallCustomInstruction(pattern: "11---------------000-----1011011", handler: _ => LogUnsupported("p.mulhhsN rD, rs1, rs2, Is3")); 98 InstallCustomInstruction(pattern: "000100000000-----001-----0110011", handler: _ => LogUnsupported("p.fl1 rD, rs1")); 99 InstallCustomInstruction(pattern: "-----------------110-----0000011", handler: _ => LogUnsupported("p.elw")); 100 } 101 LogUnhandledCSRRead(string name)102 private ulong LogUnhandledCSRRead(string name) 103 { 104 this.Log(LogLevel.Error, "Reading from an unsupported CSR {0}", name); 105 return 0u; 106 } 107 LogUnhandledCSRWrite(string name, ulong value)108 private void LogUnhandledCSRWrite(string name, ulong value) 109 { 110 this.Log(LogLevel.Error, "Writing to an unsupported CSR {0} value: 0x{1:X}", name, value); 111 } 112 MultiplyAccumulate(ulong opcode, bool operationAdd, string log)113 private void MultiplyAccumulate(ulong opcode, bool operationAdd, string log) 114 { 115 this.Log(LogLevel.Noisy, "({0}) at PC={1:X}", log, PC.RawValue); 116 117 var rD = (int)BitHelper.GetValue(opcode, 7, 5); 118 var rs1 = (int)BitHelper.GetValue(opcode, 15, 5); 119 var rs2 = (int)BitHelper.GetValue(opcode, 20, 5); 120 121 var rDValue = (long)GetRegister(rD).RawValue; 122 var rs1Value = (long)GetRegister(rs1).RawValue; 123 var rs2Value = (long)GetRegister(rs2).RawValue; 124 125 var result = (ulong)(operationAdd 126 ? rDValue + rs1Value * rs2Value 127 : rDValue - rs1Value * rs2Value); 128 129 SetRegister(rD, result); 130 } 131 LoadRegisterImmediate(ulong opcode, Width width, BitExtension extension, string log)132 private void LoadRegisterImmediate(ulong opcode, Width width, BitExtension extension, string log) 133 { 134 this.Log(LogLevel.Noisy, "({0}) at PC={1:X}", log, PC.RawValue); 135 // rD = Sext/Zext(Mem8/16/32(rs1)) 136 // rs1 += Imm[11:0] 137 // It seems that Imm should be extended, but the docs do not confirm it explicitly 138 var imm = (int)BitHelper.SignExtend((uint)BitHelper.GetValue(opcode, 20, 12), 12); 139 var rD = (int)BitHelper.GetValue(opcode, 7, 5); 140 var rs1 = (int)BitHelper.GetValue(opcode, 15, 5); 141 var rs1Value = (long)GetRegister(rs1).RawValue; 142 SetRegister(rD, GetMemValue(width, extension, (ulong)rs1Value)); 143 SetRegister(rs1, (ulong)(rs1Value + imm)); 144 } 145 LoadRegisterRegister(ulong opcode, Width width, BitExtension extension, string log, bool postIncrement = false)146 private void LoadRegisterRegister(ulong opcode, Width width, BitExtension extension, string log, bool postIncrement = false) 147 { 148 this.Log(LogLevel.Noisy, "({0}) at PC={1:X}", log, PC.RawValue); 149 // with post-increment: 150 // rD = Sext/Zext(Mem8/16/32(rs1)) 151 // rs1 += rs2 152 // without post-increment: 153 // rD = Sext/Zext(Mem8/16/32(rs1 + rs2)) 154 var rD = (int)BitHelper.GetValue(opcode, 7, 5); 155 var rs1 = (int)BitHelper.GetValue(opcode, 15, 5); 156 var rs1Value = GetRegister(rs1).RawValue; 157 var rs2 = (int)BitHelper.GetValue(opcode, 20, 5); 158 var rs2Value = GetRegister(rs2).RawValue; 159 SetRegister(rD, GetMemValue(width, extension, postIncrement ? rs1Value : rs1Value + rs2Value)); 160 if(postIncrement) 161 { 162 SetRegister(rs1, rs1Value + rs2Value); 163 } 164 } 165 StoreRegisterImmediate(ulong opcode, Width width, string log)166 private void StoreRegisterImmediate(ulong opcode, Width width, string log) 167 { 168 this.Log(LogLevel.Noisy, "({0}) at PC={1:X}", log, PC.RawValue); 169 // Mem8/16/32(rs1) = rs2 170 // rs1 += Imm[11:0] 171 var imm = (int)BitHelper.SignExtend((uint)((BitHelper.GetValue(opcode, 25, 7) << 5) | BitHelper.GetValue(opcode, 7, 5)), 12); 172 var rs2 = (int)BitHelper.GetValue(opcode, 20, 5); 173 var rs1 = (int)BitHelper.GetValue(opcode, 15, 5); 174 var rs2Value = GetRegister(rs2).RawValue; 175 var rs1Value = (long)GetRegister(rs1).RawValue; 176 SetMemValue(width, rs2Value, (ulong)rs1Value); 177 SetRegister(rs1, (ulong)(rs1Value + imm)); 178 } 179 StoreRegisterRegister(ulong opcode, Width width, string log, bool postIncrement = false)180 private void StoreRegisterRegister(ulong opcode, Width width, string log, bool postIncrement = false) 181 { 182 this.Log(LogLevel.Noisy, "({0}) at PC={1:X}", log, PC.RawValue); 183 // with post-increment: 184 // Mem8/16/32(rs1) = rs2 185 // rs1 += rs3 186 // without post-increment: 187 // Mem8/16/32(rs1 + rs3) = rs2 188 var rs2 = (int)BitHelper.GetValue(opcode, 20, 5); 189 var rs3 = (int)BitHelper.GetValue(opcode, 7, 5); 190 var rs1 = (int)BitHelper.GetValue(opcode, 15, 5); 191 var rs1Value = GetRegister(rs1).RawValue; 192 var rs3Value = GetRegister(rs3).RawValue; 193 var rs2Value = GetRegister(rs2).RawValue; 194 SetMemValue(width, rs2Value, postIncrement ? rs1Value : rs1Value + rs3Value); 195 if(postIncrement) 196 { 197 SetRegister(rs1, rs1Value + rs3Value); 198 } 199 } 200 CompareRegisters(ulong opcode, ComparisonType type, Sign sign, string log)201 private void CompareRegisters(ulong opcode, ComparisonType type, Sign sign, string log) 202 { 203 this.Log(LogLevel.Noisy, "({0}) at PC=0x{1:X}", log, PC.RawValue); 204 var rD = (int)BitHelper.GetValue(opcode, 7, 5); 205 var rs1 = (int)BitHelper.GetValue(opcode, 15, 5); 206 var rs1Value = GetRegister(rs1).RawValue; 207 var rs2 = (int)BitHelper.GetValue(opcode, 20, 5); 208 var rs2Value = GetRegister(rs2).RawValue; 209 var result = 0UL; 210 if(type == ComparisonType.Min && sign == Sign.Signed) 211 { 212 result = (int)rs1Value < (int)rs2Value ? rs1Value : rs2Value; 213 } 214 else if(type == ComparisonType.Min && sign == Sign.Unsigned) 215 { 216 result = rs1Value < rs2Value ? rs1Value : rs2Value; 217 } 218 else if(type == ComparisonType.Max && sign == Sign.Signed) 219 { 220 result = (int)rs1Value < (int)rs2Value ? rs2Value : rs1Value; 221 } 222 else if(type == ComparisonType.Max && sign == Sign.Unsigned) 223 { 224 result = rs1Value < rs2Value ? rs2Value : rs1Value; 225 } 226 else 227 { 228 this.Log(LogLevel.Error, "Could not execute compare instruction: {0}", log); 229 } 230 SetRegister(rD, result); 231 } 232 ManipulateBitsInRegister(ulong opcode, Source source, Operation operation, Width width, Sign sign, string log)233 private void ManipulateBitsInRegister(ulong opcode, Source source, Operation operation, Width width, Sign sign, string log) 234 { 235 this.Log(LogLevel.Noisy, "({0}) at PC={1:X}", log, PC.RawValue); 236 var rD = (int)BitHelper.GetValue(opcode, 7, 5); 237 var rs1 = (int)BitHelper.GetValue(opcode, 15, 5); 238 var is2 = (int)BitHelper.GetValue(opcode, 20, 5); 239 var is3 = (int)BitHelper.GetValue(opcode, 25, 5); 240 var rs1Value = GetRegister(rs1).RawValue; 241 if(source == Source.Register) 242 { 243 var rs2 = (int)BitHelper.GetValue(opcode, 20, 5); 244 var rs2Value = GetRegister(rs2).RawValue; 245 is2 = (int)BitHelper.GetValue(rs2Value, 0, 5); 246 is3 = (int)BitHelper.GetValue(rs2Value, 5, 5); 247 } 248 var rDValue = GetRegister(rD).RawValue; 249 if(is2 + is3 > 32) 250 { 251 this.Log(LogLevel.Error, "Sum of operands Is3 an Is2 is equal to {0} but should not be larger than 32", is2 + is3); 252 return; 253 } 254 var result = 0UL; 255 switch(operation) 256 { 257 case Operation.Set: 258 // p.bset: 259 // rD = rs1 | (((1 << (Is3 + 1)) - 1) << Is2) 260 // p.bsetr: 261 // rD = rs1 | (((1 << (rs2[9:5]+1)) - 1) << rs2[4:0]) 262 result = rs1Value | ((ulong)((1 << (is3 + 1)) - 1) << is2); 263 break; 264 case Operation.Insert: 265 // p.insert: 266 // rD = rD | (rs1[Is3:0] << Is2) 267 // p.insertr: 268 // rD = rD | (rs1[rs2[9:5]:0] << rs2[4:0]) 269 result = rDValue | (BitHelper.GetValue(rs1Value, 0, is3 + 1) << is2); 270 break; 271 case Operation.Extract: 272 result = ExtractBits(width, sign, is2, is3, rs1Value); 273 break; 274 case Operation.Clear: 275 // p.bclr: 276 // rD = rs1 & ~(((1 << (Is3 + 1)) - 1) << Is2) 277 // p.bclrr: 278 // rD = rs1 & ~(((1 << (rs2[9:5]+1)) - 1) << rs2[4:0]) 279 result = rs1Value & (~(ulong)(((1 << (is3 + 1)) - 1) << is2)); 280 break; 281 default: 282 this.Log(LogLevel.Error, "Encountered an unexpected option: {0}", sign); 283 break; 284 } 285 SetRegister(rD, result); 286 } 287 BranchIf(ulong opcode, Equality equality, string log)288 private void BranchIf(ulong opcode, Equality equality, string log) 289 { 290 this.Log(LogLevel.Noisy, "({0}) at PC={1:X}", log, PC.RawValue); 291 var rs1 = (int)BitHelper.GetValue(opcode, 15, 5); 292 var rs1Value = (long)GetRegister(rs1).RawValue; 293 var imm5 = (int)BitHelper.SignExtend((uint)BitHelper.GetValue(opcode, 20, 5), 5); 294 if((equality == Equality.NotEqual && rs1Value != imm5) || (equality == Equality.Equal && rs1Value == imm5)) 295 { 296 var imm12 = (int)BitHelper.SignExtend((uint)((BitHelper.GetValue(opcode, 31, 1) << 11) | (BitHelper.GetValue(opcode, 7, 1) << 10) | (BitHelper.GetValue(opcode, 25, 6) << 4) | BitHelper.GetValue(opcode, 8, 4)), 12); 297 var newPC = (uint)((uint)GetRegister((int)RiscV32Registers.PC).RawValue + (imm12 << 1)); 298 PC = newPC; 299 } 300 } 301 ExtractBits(Width width, Sign sign, int is2, int is3, ulong rs1Value)302 private ulong ExtractBits(Width width, Sign sign, int is2, int is3, ulong rs1Value) 303 { 304 // This seems to be contradicting the documentation, but experimentally 305 // makes things work. 306 is3++; 307 var result = 0UL; 308 switch(width) 309 { 310 case Width.Byte: 311 // p.extbs rD, rs1 312 // rD = Sext(rs1[7:0]) 313 // p.extbz rD, rs1 314 // rD = Zext(rs1[7:0]) 315 result = sign == Sign.Signed 316 ? BitHelper.SignExtend((uint)BitHelper.GetValue(rs1Value, 0, 8), 8) 317 : BitHelper.GetValue(rs1Value, 0, 8); 318 break; 319 case Width.HalfWord: 320 // p.exths rD, rs1 321 // rD = Sext(rs1[15:0]) 322 // p.exthz rD, rs1 323 // rD = Zext(rs1[15:0]) 324 result = sign == Sign.Signed 325 ? BitHelper.SignExtend((uint)BitHelper.GetValue(rs1Value, 0, 16), 16) 326 : BitHelper.GetValue(rs1Value, 0, 16); 327 break; 328 case Width.Word: 329 // p.extract rD, rs1, Is3, Is2 330 // rD = Sext((rs1 & ((1 << Is3) - 1) << Is2) >> Is2) 331 // p.extractu rD, rs1, Is3, Is2 332 // rD = Zext((rs1 & ((1 << Is3) - 1) << Is2) >> Is2) 333 // p.extractr rD, rs1, rs2 334 // rD = Sext((rs1 & ((1 << rs2[9:5]) - 1) << rs2[4:0]) >> rs2[4:0]) 335 // p.extractur rD, rs1, rs2 336 // rD = Zext((rs1 & ((1 << rs2[9:5]) - 1) << rs2[4:0]) >> rs2[4:0]) 337 var temp = ((int)rs1Value & ((1 << is3) - 1) << is2) >> is2; 338 result = sign == Sign.Signed 339 ? BitHelper.SignExtend((uint)temp, 32 - is2) 340 : (uint)temp; 341 break; 342 default: 343 this.Log(LogLevel.Error, "Encountered an unexpected option: {0}", sign); 344 break; 345 } 346 return result; 347 } 348 SetMemValue(Width width, ulong value, ulong address)349 private void SetMemValue(Width width, ulong value, ulong address) 350 { 351 switch(width) 352 { 353 case Width.Byte: 354 WriteByteToBus(address, (uint)value); 355 break; 356 case Width.HalfWord: 357 WriteWordToBus(address, (uint)value); 358 break; 359 case Width.Word: 360 WriteDoubleWordToBus(address, (uint)value); 361 break; 362 default: 363 this.Log(LogLevel.Error, "Encountered an unexpected option: {0}", width); 364 break; 365 } 366 } 367 GetMemValue(Width width, BitExtension extension, ulong address)368 private ulong GetMemValue(Width width, BitExtension extension, ulong address) 369 { 370 var mem = 0UL; 371 switch(width) 372 { 373 case Width.Byte: 374 mem = extension == BitExtension.Sign ? BitHelper.SignExtend(ReadByteFromBus(address), 8) : ReadByteFromBus(address); 375 break; 376 case Width.HalfWord: 377 mem = extension == BitExtension.Sign ? BitHelper.SignExtend(ReadWordFromBus(address), 16) : ReadWordFromBus(address); 378 break; 379 case Width.Word: 380 mem = ReadDoubleWordFromBus(address); 381 break; 382 default: 383 this.Log(LogLevel.Error, "Encountered an unexpected option: {0}", width); 384 break; 385 } 386 return mem; 387 } 388 LogUnsupported(string text)389 private void LogUnsupported(string text) 390 { 391 this.Log(LogLevel.Error, "Encountered unsupported instruction: ({0}) at PC={1:X}", text, PC); 392 } 393 394 private enum Equality 395 { 396 Equal, 397 NotEqual 398 } 399 400 private enum ComparisonType 401 { 402 Max, 403 Min 404 } 405 406 private enum Sign 407 { 408 Signed, 409 Unsigned 410 } 411 412 private enum Width 413 { 414 Byte, 415 HalfWord, 416 Word 417 } 418 419 private enum Operation 420 { 421 Extract, 422 Insert, 423 Clear, 424 Set 425 } 426 427 private enum Source 428 { 429 Register, 430 Immediate 431 } 432 private enum BitExtension 433 { 434 Sign, 435 Zero 436 } 437 438 private enum CustomCSR 439 { 440 PerformanceCounterMode = 0x7a1, 441 StackCheckEnable = 0x7d0, 442 StackBase = 0x7d1, 443 StackEnd = 0x7d2, 444 HardwareLoop0Start = 0x7c0, 445 HardwareLoop0End = 0x7c1, 446 HardwareLoop0Counter = 0x7c2, 447 HardwareLoop1Start = 0x7c4, 448 HardwareLoop1End = 0x7d5, 449 HardwareLoop1Counter = 0x7d6 450 } 451 } 452 } 453