No public description PiperOrigin-RevId: 638333178 Change-Id: I35d12b0c2af0e182c4b1ce1344d07b54966c4196
diff --git a/cheriot/cheriot_register.cc b/cheriot/cheriot_register.cc index d4c64f3..11dc8cb 100644 --- a/cheriot/cheriot_register.cc +++ b/cheriot/cheriot_register.cc
@@ -317,6 +317,8 @@ return (object_type() == kSentry) || (object_type() == kInterruptEnablingSentry) || (object_type() == kInterruptDisablingSentry) || + (object_type() == kInterruptEnablingReturnSentry) || + (object_type() == kInterruptDisablingReturnSentry) || (object_type() == kSealedExecutable6) || (object_type() == kSealedExecutable7); } else { @@ -357,6 +359,8 @@ case kSentry: case kInterruptEnablingSentry: case kInterruptDisablingSentry: + case kInterruptEnablingReturnSentry: + case kInterruptDisablingReturnSentry: case kSealedExecutable6: case kSealedExecutable7: // The sealing type is ok. @@ -429,7 +433,12 @@ bool CheriotRegister::IsSentry() const { return !is_null_ && (object_type() >= kSentry) && - (object_type() <= kInterruptEnablingSentry); + (object_type() <= kInterruptEnablingReturnSentry); +} + +bool CheriotRegister::IsBackwardSentry() const { + return !is_null_ && ((object_type() == kInterruptEnablingReturnSentry) || + (object_type() == kInterruptDisablingReturnSentry)); } void CheriotRegister::CopyFrom(const CheriotRegister &other) {
diff --git a/cheriot/cheriot_register.h b/cheriot/cheriot_register.h index 57c19f2..c62ddbb 100644 --- a/cheriot/cheriot_register.h +++ b/cheriot/cheriot_register.h
@@ -72,8 +72,8 @@ kSentry = 1, kInterruptDisablingSentry = 2, kInterruptEnablingSentry = 3, - kReserved4 = 4, - kReserved5 = 5, + kInterruptDisablingReturnSentry = 4, + kInterruptEnablingReturnSentry = 5, kSealedExecutable6 = 6, kSealedExecutable7 = 7, kReserved8 = 8, @@ -149,6 +149,8 @@ bool IsUnsealed() const; // Returns true if the capability is a sentry. bool IsSentry() const; + // Returns true if the capability is a backward sentry. + bool IsBackwardSentry() const; // Clears the tag. void Invalidate() { set_tag(false); } // Set bounds, return true if they're precise, i.e., that the base and length
diff --git a/cheriot/cheriot_state.cc b/cheriot/cheriot_state.cc index 49e8183..525c5c8 100644 --- a/cheriot/cheriot_state.cc +++ b/cheriot/cheriot_state.cc
@@ -613,7 +613,8 @@ void CheriotState::Trap(bool is_interrupt, uint64_t trap_value, uint64_t exception_code, uint64_t epc, const Instruction *inst) { - // Call the handler. + // LOG(INFO) << "Trap: " << std::hex << is_interrupt << " " << trap_value << " + // " << exception_code << " " << epc; Call the handler. if (on_trap_ != nullptr) { bool res = on_trap_(is_interrupt, trap_value, exception_code, epc, inst); // If the handler returns true, the trap has been handled. Just return.
diff --git a/cheriot/cheriot_test_rig_decoder.cc b/cheriot/cheriot_test_rig_decoder.cc index 5038397..c1ff08f 100644 --- a/cheriot/cheriot_test_rig_decoder.cc +++ b/cheriot/cheriot_test_rig_decoder.cc
@@ -79,7 +79,6 @@ cheriot_encoding_->ParseInstruction(inst_word); auto format = cheriot_encoding_->GetFormat(SlotEnum::kRiscv32Cheriot, 0); auto opcode = cheriot_encoding_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0); - // Extract the numerical register specifies of the instruction. int rd = 0; int rs1 = 0; @@ -124,11 +123,13 @@ rs2 = 0; break; } + /* case FormatEnum::kR4Type: // 4 reg operands, rd, rs1, rs3, and rs4. rd = encoding::r4_type::ExtractRd(inst_word); rs1 = encoding::r4_type::ExtractRs1(inst_word); rs2 = encoding::r4_type::ExtractRs2(inst_word); break; + */ case FormatEnum::kRType: // 3 reg operands: rd, rs1, and rs2. rd = encoding::r_type::ExtractRd(inst_word); rs1 = encoding::r_type::ExtractRs1(inst_word); @@ -220,7 +221,7 @@ rs1 = encoding::c_r::ExtractRs1(inst_word16); rs2 = 0; break; - case OpcodeEnum::kCheriotCjalr: + case OpcodeEnum::kCheriotCjalrCra: rd = 1; rs1 = encoding::c_r::ExtractRs1(inst_word16); rs2 = 0; @@ -263,6 +264,11 @@ if (opcode == OpcodeEnum::kCslli) { rs1 = 0; } + if ((opcode == OpcodeEnum::kHint) || (opcode == OpcodeEnum::kChint)) { + rs1 = 0; + rs2 = 0; + rd = 0; + } decode_info.rd = rd; decode_info.rs1 = rs1; decode_info.rs2 = rs2;
diff --git a/cheriot/debug_command_shell.cc b/cheriot/debug_command_shell.cc index 3b24c1d..70727f8 100644 --- a/cheriot/debug_command_shell.cc +++ b/cheriot/debug_command_shell.cc
@@ -1422,8 +1422,9 @@ // If it's not a jump-and-link, it's a single step. if ((inst->opcode() != *isa32::OpcodeEnum::kCheriotJal) && (inst->opcode() != *isa32::OpcodeEnum::kCheriotJalr) && + (inst->opcode() != *isa32::OpcodeEnum::kCheriotJalrCra) && (inst->opcode() != *isa32::OpcodeEnum::kCheriotCjal) && - (inst->opcode() != *isa32::OpcodeEnum::kCheriotCjalr)) { + (inst->opcode() != *isa32::OpcodeEnum::kCheriotCjalrCra)) { return core_access_[current_core_].debug_interface->Step(1).status(); } // If it is a jump-and-link, we have to set a breakpoint on the instruction
diff --git a/cheriot/riscv_cheriot_encoding.cc b/cheriot/riscv_cheriot_encoding.cc index d3c66eb..df9b3cd 100644 --- a/cheriot/riscv_cheriot_encoding.cc +++ b/cheriot/riscv_cheriot_encoding.cc
@@ -188,6 +188,7 @@ auto *csr = res.value(); return new generic::ImmediateOperand<uint32_t>(csr_indx, csr->name()); }); + /* source_op_getters_.emplace(*SourceOpEnum::kFrs1, [this]() { int num = encoding::r_type::ExtractRs1(inst_word_); return GetRegisterSourceOp<RVFpRegister>( @@ -206,6 +207,7 @@ state_, absl::StrCat(CheriotState::kFregPrefix, num), kFRegisterAliases[num]); }); + */ source_op_getters_.emplace(*SourceOpEnum::kICbImm8, [this]() { return new generic::ImmediateOperand<int32_t>( encoding::inst16_format::ExtractBimm(inst_word_)); @@ -289,6 +291,7 @@ source_op_getters_.emplace(*SourceOpEnum::kPcc, [this]() { return GetRegisterSourceOp<CheriotRegister>(state_, "pcc", "pcc"); }); + /* source_op_getters_.emplace(*SourceOpEnum::kRm, [this]() -> SourceOperandInterface * { uint32_t rm = (inst_word_ >> 12) & 0x7; @@ -313,6 +316,7 @@ return nullptr; } }); + */ source_op_getters_.emplace( *SourceOpEnum::kRd, [this]() -> SourceOperandInterface * { int num = encoding::r_type::ExtractRd(inst_word_); @@ -482,9 +486,11 @@ state_, absl::StrCat(CheriotState::kXregPrefix, 1), latency, kXRegisterAliases[1]); }); + /* dest_op_getters_.emplace(*DestOpEnum::kFflags, [this](int latency) { return GetCSRSetBitsDestinationOp<uint32_t>(state_, "fflags", latency, ""); }); + */ dest_op_getters_.emplace(*DestOpEnum::kNone, [](int latency) { return nullptr; }); }
diff --git a/cheriot/riscv_cheriot_instructions.cc b/cheriot/riscv_cheriot_instructions.cc index b97e720..a23bc7d 100644 --- a/cheriot/riscv_cheriot_instructions.cc +++ b/cheriot/riscv_cheriot_instructions.cc
@@ -202,8 +202,8 @@ cd->set_address(instruction->address() + instruction->size()); bool interrupt_enable = state->mstatus()->mie(); (void)cd->Seal(*state->sealing_root(), - interrupt_enable ? CapReg::kInterruptEnablingSentry - : CapReg::kInterruptDisablingSentry); + interrupt_enable ? CapReg::kInterruptEnablingReturnSentry + : CapReg::kInterruptDisablingReturnSentry); // Update pcc. pcc->set_address(new_pc); state->set_branch(true); @@ -222,14 +222,24 @@ // Helper function to check for exceptions for Jr and Jalr. static bool CheriotCJrCheck(const Instruction *instruction, uint64_t new_pc, - uint32_t offset, const CheriotRegister *cs1) { + uint32_t offset, const CheriotRegister *cs1, + bool has_dest, bool uses_ra) { auto *state = static_cast<CheriotState *>(instruction->state()); if (!cs1->tag()) { state->HandleCheriRegException(instruction, instruction->address(), EC::kCapExTagViolation, cs1); return false; } - if (cs1->IsSealed() && (!cs1->IsSentry() || offset != 0)) { + bool ok = false; + ok |= !has_dest && uses_ra && cs1->IsBackwardSentry(); + ok |= !has_dest && !uses_ra && + ((cs1->object_type() == CapReg::kUnsealed) || + (cs1->object_type() == CapReg::kSentry)); + ok |= has_dest && ((cs1->object_type() == CapReg::kUnsealed) || + (cs1->object_type() == CapReg::kSentry)); + ok |= has_dest && uses_ra && (cs1->object_type() >= CapReg::kUnsealed) && + (cs1->object_type() <= CapReg::kInterruptEnablingSentry); + if ((cs1->IsSealed() && offset != 0) || !ok) { state->HandleCheriRegException(instruction, instruction->address(), EC::kCapExSealViolation, cs1); return false; @@ -248,63 +258,41 @@ return true; } -void CheriotCJalr(const Instruction *instruction) { - // TODO(torerik): fix this mess. +static inline void CheriotCJalrHelper(const Instruction *instruction, + bool has_dest, bool uses_ra) { auto *state = static_cast<CheriotState *>(instruction->state()); auto *cs1 = GetCapSource(instruction, 0); auto offset = generic::GetInstructionSource<uint32_t>(instruction, 1); auto *pcc = state->pcc(); auto new_pc = offset + cs1->address(); new_pc &= ~0b1ULL; - if (!CheriotCJrCheck(instruction, new_pc, offset, cs1)) { + if (!CheriotCJrCheck(instruction, new_pc, offset, cs1, has_dest, uses_ra)) { return; } - // Update link register. - state->temp_reg()->CopyFrom(*pcc); - state->temp_reg()->set_address(instruction->address() + instruction->size()); auto *mstatus = state->mstatus(); - bool interrupt_enable = (mstatus->GetUint32() & 0b1000) != 0; - auto status = state->temp_reg()->Seal( - *state->sealing_root(), interrupt_enable - ? CapReg::kInterruptEnablingSentry - : CapReg::kInterruptDisablingSentry); - if (!status.ok()) { - LOG(ERROR) << "Failed to seal: " << status; - return; - } - // Update pcc. - pcc->CopyFrom(*cs1); - // If the new pcc is a sentry, unseal and set/clear mie accordingly. - if (pcc->IsSentry()) { - if (pcc->object_type() != CapReg::kSentry) { - interrupt_enable = pcc->object_type() == CapReg::kInterruptEnablingSentry; - mstatus->set_mie(interrupt_enable); - mstatus->Submit(); + if (has_dest) { + // Update link register. + state->temp_reg()->CopyFrom(*pcc); + state->temp_reg()->set_address(instruction->address() + + instruction->size()); + bool interrupt_enable = (mstatus->GetUint32() & 0b1000) != 0; + auto status = state->temp_reg()->Seal( + *state->sealing_root(), interrupt_enable + ? CapReg::kInterruptEnablingReturnSentry + : CapReg::kInterruptDisablingReturnSentry); + if (!status.ok()) { + LOG(ERROR) << "Failed to seal: " << status; + return; } - (void)pcc->Unseal(*state->sealing_root(), pcc->object_type()); } - pcc->set_address(new_pc); - state->set_branch(true); - auto *cd = GetCapDest(instruction, 0); - cd->CopyFrom(*state->temp_reg()); -} - -void CheriotCJr(const Instruction *instruction) { - auto *state = static_cast<CheriotState *>(instruction->state()); - auto *cs1 = GetCapSource(instruction, 0); - auto offset = generic::GetInstructionSource<uint32_t>(instruction, 1); - auto *pcc = state->pcc(); - auto new_pc = offset + cs1->address(); - new_pc &= ~0b1ULL; - if (!CheriotCJrCheck(instruction, new_pc, offset, cs1)) return; // Update pcc. pcc->CopyFrom(*cs1); // If the new pcc is a sentry, unseal and set/clear mie accordingly. if (pcc->IsSentry()) { if (pcc->object_type() != CapReg::kSentry) { bool interrupt_enable = - pcc->object_type() == CapReg::kInterruptEnablingSentry; - auto *mstatus = state->mstatus(); + (pcc->object_type() == CapReg::kInterruptEnablingSentry) | + (pcc->object_type() == CapReg::kInterruptEnablingReturnSentry); mstatus->set_mie(interrupt_enable); mstatus->Submit(); } @@ -312,6 +300,33 @@ } pcc->set_address(new_pc); state->set_branch(true); + if (has_dest) { + auto *cd = GetCapDest(instruction, 0); + cd->CopyFrom(*state->temp_reg()); + } +} + +void CheriotCJalr(const Instruction *instruction) { + CheriotCJalrHelper(instruction, /*has_dest=*/true, /*uses_ra=*/false); +} + +void CheriotCJalrCra(const Instruction *instruction) { + CheriotCJalrHelper(instruction, /*has_dest=*/true, /*uses_ra=*/true); +} + +void CheriotCJrCra(const Instruction *instruction) { + CheriotCJalrHelper(instruction, /*has_dest=*/false, /*uses_ra=*/true); +} + +void CheriotCJr(const Instruction *instruction) { + CheriotCJalrHelper(instruction, /*has_dest=*/false, /*uses_ra=*/false); +} + +void CheriotCJalrZero(const Instruction *instruction) { + auto *state = static_cast<CheriotState *>(instruction->state()); + auto *cs1 = GetCapSource(instruction, 0); + state->HandleCheriRegException(instruction, instruction->address(), + EC::kCapExTagViolation, cs1); } void CheriotCLc(const Instruction *instruction) {
diff --git a/cheriot/riscv_cheriot_instructions.h b/cheriot/riscv_cheriot_instructions.h index 346bc24..ec59f87 100644 --- a/cheriot/riscv_cheriot_instructions.h +++ b/cheriot/riscv_cheriot_instructions.h
@@ -81,6 +81,15 @@ // This instruction takes 2 sources. Source 0 is the source capability, source 1 // is the offset. The pcc is implied. void CheriotCJr(const Instruction *instruction); +// This instruction takes 2 sources and one destination operand. Source 0 is the +// source capability, source 1 is the offset. Destination 0 is the link +// capability. The pcc is implied. +void CheriotCJalrCra(const Instruction *instruction); +// This instruction takes 2 sources. Source 0 is the source capability, source 1 +// is the offset. The pcc is implied. +void CheriotCJrCra(const Instruction *instruction); +// This instruction takes no sources, no destinations. +void CheriotCJalrZero(const Instruction *instruction); // This takes 2 source operands and 1 destination operand. Source 0 is the // address source capability, source 1 is the integer offset. Destination 0 is // the target capability.
diff --git a/cheriot/test/cheriot_register_test.cc b/cheriot/test/cheriot_register_test.cc index d698060..2753ffd 100644 --- a/cheriot/test/cheriot_register_test.cc +++ b/cheriot/test/cheriot_register_test.cc
@@ -349,6 +349,8 @@ if ((i == ObjectType::kSentry) || (i == ObjectType::kInterruptDisablingSentry) || (i == ObjectType::kInterruptEnablingSentry) || + (i == ObjectType::kInterruptDisablingReturnSentry) || + (i == ObjectType::kInterruptEnablingReturnSentry) || (i == ObjectType::kSealedExecutable6) || (i == ObjectType::kSealedExecutable7)) { EXPECT_TRUE(status.ok()) << status.message(); @@ -415,7 +417,7 @@ // Copy from null capability. cap_reg()->ResetNull(); cap_reg()->data_buffer()->Set<uint32_t>(0, kAddress); - cap_reg()->set_object_type(ObjectType::kReserved4); + cap_reg()->set_object_type(ObjectType::kReserved8); cap_reg()->set_reserved(1); cap_reg_copy->CopyFrom(*cap_reg()); EXPECT_FALSE(cap_reg_copy->IsValid()); @@ -430,7 +432,7 @@ // Copy from memory root capability. cap_reg()->ResetMemoryRoot(); cap_reg()->data_buffer()->Set<uint32_t>(0, kAddress); - cap_reg()->set_object_type(ObjectType::kReserved4); + cap_reg()->set_object_type(ObjectType::kReserved8); cap_reg()->set_reserved(1); (void)cap_reg()->SetBounds(kBase, kAddress + 1); cap_reg_copy->CopyFrom(*cap_reg()); @@ -445,7 +447,7 @@ // Copy from execute root capability. cap_reg()->ResetExecuteRoot(); cap_reg()->data_buffer()->Set<uint32_t>(0, kAddress); - cap_reg()->set_object_type(ObjectType::kReserved4); + cap_reg()->set_object_type(ObjectType::kReserved8); cap_reg()->set_reserved(1); (void)cap_reg()->SetBounds(kBase, kAddress + 1); cap_reg_copy->CopyFrom(*cap_reg()); @@ -460,7 +462,7 @@ // Copy from sealing root capability. cap_reg()->ResetSealingRoot(); cap_reg()->data_buffer()->Set<uint32_t>(0, kAddress); - cap_reg()->set_object_type(ObjectType::kReserved4); + cap_reg()->set_object_type(ObjectType::kReserved8); cap_reg()->set_reserved(1); (void)cap_reg()->SetBounds(kBase, kAddress + 1); cap_reg_copy->CopyFrom(*cap_reg());
diff --git a/cheriot/test/riscv_cheriot_encoding_test.cc b/cheriot/test/riscv_cheriot_encoding_test.cc index 04fc563..2f941e7 100644 --- a/cheriot/test/riscv_cheriot_encoding_test.cc +++ b/cheriot/test/riscv_cheriot_encoding_test.cc
@@ -140,33 +140,6 @@ // constexpr uint32_t kAmomaxw = 0b10100'0'0'00000'00000'010'00000'0101111; // constexpr uint32_t kAmominuw = 0b11000'0'0'00000'00000'010'00000'0101111; // constexpr uint32_t kAmomaxuw = 0b11100'0'0'00000'00000'010'00000'0101111; -// RV32F -constexpr uint32_t kFlw = 0b000000000000'00000'010'00000'0000111; -constexpr uint32_t kFsw = 0b0000000'00000'00000'010'00000'0100111; -constexpr uint32_t kFmadds = 0b00000'00'00000'00000'000'00000'1000011; -constexpr uint32_t kFmsubs = 0b00000'00'00000'00000'000'00000'1000111; -constexpr uint32_t kFnmsubs = 0b00000'00'00000'00000'000'00000'1001011; -constexpr uint32_t kFnmadds = 0b00000'00'00000'00000'000'00000'1001111; -constexpr uint32_t kFadds = 0b0000000'00000'00000'000'00000'1010011; -constexpr uint32_t kFsubs = 0b0000100'00000'00000'000'00000'1010011; -constexpr uint32_t kFmuls = 0b0001000'00000'00000'000'00000'1010011; -constexpr uint32_t kFdivs = 0b0001100'00000'00000'000'00000'1010011; -constexpr uint32_t kFsqrts = 0b0101100'00000'00000'000'00000'1010011; -constexpr uint32_t kFsgnjs = 0b0010000'00000'00000'000'00000'1010011; -constexpr uint32_t kFsgnjns = 0b0010000'00000'00000'001'00000'1010011; -constexpr uint32_t kFsgnjxs = 0b0010000'00000'00000'010'00000'1010011; -constexpr uint32_t kFmins = 0b0010100'00000'00000'000'00000'1010011; -constexpr uint32_t kFmaxs = 0b0010100'00000'00000'001'00000'1010011; -constexpr uint32_t kFcvtws = 0b1100000'00000'00000'000'00000'1010011; -constexpr uint32_t kFcvtwus = 0b1100000'00001'00000'000'00000'1010011; -constexpr uint32_t kFmvxw = 0b1110000'00000'00000'000'00000'1010011; -constexpr uint32_t kFeqs = 0b1010000'00000'00000'010'00000'1010011; -constexpr uint32_t kFlts = 0b1010000'00000'00000'001'00000'1010011; -constexpr uint32_t kFles = 0b1010000'00000'00000'000'00000'1010011; -constexpr uint32_t kFclasss = 0b1110000'00000'00000'001'00000'1010011; -constexpr uint32_t kFcvtsw = 0b1101000'00000'00000'000'00000'1010011; -constexpr uint32_t kFcvtswu = 0b1101000'00001'00000'000'00000'1010011; -constexpr uint32_t kFmvwx = 0b1111000'00000'00000'000'00000'1010011; // RV32C constexpr uint32_t kClwsp = 0b010'0'00000'00000'10; constexpr uint32_t kCldsp = 0b011'0'00000'00000'10; @@ -265,7 +238,7 @@ OpcodeEnum::kCheriotJal); enc_->ParseInstruction(SetRd(kCheriotJalr, kRdValue)); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kCheriotJalr); + OpcodeEnum::kCheriotJalrCra); enc_->ParseInstruction(kBeq); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kBeq); enc_->ParseInstruction(kBne); @@ -429,72 +402,6 @@ // OpcodeEnum::kAmomaxuw); // } -TEST_F(RiscVCheriotEncodingTest, RV32FOpcodes) { - // RV32F - enc_->ParseInstruction(kFlw); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFlw); - enc_->ParseInstruction(kFsw); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFsw); - enc_->ParseInstruction(kFmadds); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFmaddS); - enc_->ParseInstruction(kFmsubs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFmsubS); - enc_->ParseInstruction(kFnmsubs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFnmsubS); - enc_->ParseInstruction(kFnmadds); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFnmaddS); - enc_->ParseInstruction(kFadds); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFaddS); - enc_->ParseInstruction(kFsubs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFsubS); - enc_->ParseInstruction(kFmuls); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFmulS); - enc_->ParseInstruction(kFdivs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFdivS); - enc_->ParseInstruction(kFsqrts); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFsqrtS); - enc_->ParseInstruction(kFsgnjs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFsgnjS); - enc_->ParseInstruction(kFsgnjns); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFsgnjnS); - enc_->ParseInstruction(kFsgnjxs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFsgnjxS); - enc_->ParseInstruction(kFmins); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFminS); - enc_->ParseInstruction(kFmaxs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFmaxS); - enc_->ParseInstruction(kFcvtws); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFcvtWs); - enc_->ParseInstruction(kFcvtwus); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFcvtWus); - enc_->ParseInstruction(kFmvxw); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFmvXw); - enc_->ParseInstruction(kFeqs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFcmpeqS); - enc_->ParseInstruction(kFlts); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFcmpltS); - enc_->ParseInstruction(kFles); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFcmpleS); - enc_->ParseInstruction(kFclasss); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFclassS); - enc_->ParseInstruction(kFcvtsw); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFcvtSw); - enc_->ParseInstruction(kFcvtswu); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kFcvtSwu); - enc_->ParseInstruction(kFmvwx); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kFmvWx); -} - // Test for decoding compact opcodes. TEST_F(RiscVCheriotEncodingTest, RV32COpcodes) { enc_->ParseInstruction(Set16Rd(kClwsp, 1)); @@ -530,10 +437,10 @@ OpcodeEnum::kCheriotCjal); enc_->ParseInstruction(Set16Rd(kCheriotCjr, 1)); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kCheriotCjr); + OpcodeEnum::kCheriotCjrCra); enc_->ParseInstruction(Set16Rd(kCheriotCjalr, 1)); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kCheriotCjalr); + OpcodeEnum::kCheriotCjalrCra); enc_->ParseInstruction(kCbeqz); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kCbeqz); enc_->ParseInstruction(kCbnez); @@ -626,13 +533,13 @@ OpcodeEnum::kCheriotJal); enc_->ParseInstruction(SetRd(kCheriotJalr, kRdValue)); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kCheriotJalr); + OpcodeEnum::kCheriotJalrCra); enc_->ParseInstruction(kCheriotJal); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kCheriotJ); enc_->ParseInstruction(kCheriotJalr); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), - OpcodeEnum::kCheriotJr); + OpcodeEnum::kCheriotJalrZero); enc_->ParseInstruction(kCheriotLc); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kCheriotLc);
diff --git a/cheriot/test/riscv_cheriot_instructions_test.cc b/cheriot/test/riscv_cheriot_instructions_test.cc index e43d550..c0bc046 100644 --- a/cheriot/test/riscv_cheriot_instructions_test.cc +++ b/cheriot/test/riscv_cheriot_instructions_test.cc
@@ -64,7 +64,7 @@ using ::mpact::sim::cheriot::CheriotCGetType; using ::mpact::sim::cheriot::CheriotCIncAddr; using ::mpact::sim::cheriot::CheriotCJal; -using ::mpact::sim::cheriot::CheriotCJalr; +using ::mpact::sim::cheriot::CheriotCJalrCra; using ::mpact::sim::cheriot::CheriotCLc; using ::mpact::sim::cheriot::CheriotCLcChild; using ::mpact::sim::cheriot::CheriotCMove; @@ -83,12 +83,13 @@ using ::mpact::sim::cheriot::CheriotCTestSubset; using ::mpact::sim::cheriot::CheriotCUnseal; // Register name definitions. -constexpr char kC1[] = "c1"; -constexpr char kC2[] = "c2"; -constexpr char kC3[] = "c3"; -constexpr char kC4[] = "c4"; +constexpr char kCra[] = "c1"; +constexpr char kC1[] = "c11"; +constexpr char kC2[] = "c12"; +constexpr char kC3[] = "c13"; +constexpr char kC4[] = "c14"; // Register number definitions. -constexpr int kC1Num = 1; +constexpr int kC1Num = 11; constexpr int kPccNum = 0b1'00000; constexpr uint32_t kInstAddress = 0x2468; @@ -111,7 +112,8 @@ {kC1, &c1_reg_}, {kC2, &c2_reg_}, {kC3, &c3_reg_}, - {kC4, &c4_reg_}}) { + {kC4, &c4_reg_}, + {kCra, &cra_reg_}}) { *cap_reg_ptr = state_->GetRegister<CheriotRegister>(reg_name).first; } state_->set_on_trap([this](bool is_interrupt, uint64_t trap_value, @@ -213,6 +215,7 @@ CheriotRegister *c2_reg() { return c2_reg_; } CheriotRegister *c3_reg() { return c3_reg_; } CheriotRegister *c4_reg() { return c4_reg_; } + CheriotRegister *cra_reg() { return cra_reg_; } absl::BitGen &bitgen() { return bitgen_; } bool trap_taken() { return trap_taken_; } bool trap_is_interrupt() { return trap_is_interrupt_; } @@ -229,6 +232,7 @@ CheriotRegister *c2_reg_; CheriotRegister *c3_reg_; CheriotRegister *c4_reg_; + CheriotRegister *cra_reg_; absl::BitGen bitgen_; bool trap_taken_ = false; bool trap_is_interrupt_ = false; @@ -554,7 +558,7 @@ EXPECT_EQ(state()->pcc()->address(), inst()->address() + 0x200); EXPECT_TRUE(c3_reg()->tag()); EXPECT_TRUE(c3_reg()->IsSentry()); - EXPECT_EQ(c3_reg()->object_type(), OT::kInterruptEnablingSentry); + EXPECT_EQ(c3_reg()->object_type(), OT::kInterruptEnablingReturnSentry); EXPECT_TRUE(state()->pcc()->tag()); // Set interrupt enable to false. state()->mstatus()->set_mie(0); @@ -566,7 +570,7 @@ EXPECT_EQ(state()->pcc()->address(), inst()->address() + 0x200); EXPECT_TRUE(c3_reg()->tag()); EXPECT_TRUE(c3_reg()->IsSentry()); - EXPECT_EQ(c3_reg()->object_type(), OT::kInterruptDisablingSentry); + EXPECT_EQ(c3_reg()->object_type(), OT::kInterruptDisablingReturnSentry); EXPECT_TRUE(state()->pcc()->tag()); } @@ -606,8 +610,8 @@ // Jump and link register (capability) indirect - no traps, unsealed source. TEST_F(RiscVCheriotInstructionsTest, CJalr) { - inst()->set_semantic_function(&CheriotCJalr); - AppendCapabilityOperands(inst(), {kC1, kC2}, {kC3}); + inst()->set_semantic_function(&CheriotCJalrCra); + AppendCapabilityOperands(inst(), {kC1, kC2}, {kCra}); state()->pcc()->set_address(inst()->address()); // Set up the destination capability. c1_reg()->ResetExecuteRoot(); @@ -622,9 +626,9 @@ EXPECT_FALSE(trap_taken()) << "ec: " << std::hex << trap_exception_code() << " value: " << trap_value(); EXPECT_EQ(state()->pcc()->address(), inst()->address() + 0x200); - EXPECT_TRUE(c3_reg()->tag()); - EXPECT_TRUE(c3_reg()->IsSentry()); - EXPECT_EQ(c3_reg()->object_type(), OT::kInterruptEnablingSentry); + EXPECT_TRUE(cra_reg()->tag()); + EXPECT_TRUE(cra_reg()->IsSentry()); + EXPECT_EQ(cra_reg()->object_type(), OT::kInterruptEnablingReturnSentry); EXPECT_TRUE(state()->pcc()->tag()); // Set interrupt enable to false. state()->mstatus()->set_mie(0); @@ -634,16 +638,16 @@ EXPECT_FALSE(trap_taken()) << "ec: " << std::hex << trap_exception_code() << " value: " << trap_value(); EXPECT_EQ(state()->pcc()->address(), inst()->address() + 0x200); - EXPECT_TRUE(c3_reg()->tag()); - EXPECT_TRUE(c3_reg()->IsSentry()); - EXPECT_EQ(c3_reg()->object_type(), OT::kInterruptDisablingSentry); + EXPECT_TRUE(cra_reg()->tag()); + EXPECT_TRUE(cra_reg()->IsSentry()); + EXPECT_EQ(cra_reg()->object_type(), OT::kInterruptDisablingReturnSentry); EXPECT_TRUE(state()->pcc()->tag()); } // Jump and link register (capability) indirect - no traps, sentry. TEST_F(RiscVCheriotInstructionsTest, CJalrSentry) { - inst()->set_semantic_function(&CheriotCJalr); - AppendCapabilityOperands(inst(), {kC1, kC2}, {kC3}); + inst()->set_semantic_function(&CheriotCJalrCra); + AppendCapabilityOperands(inst(), {kC1, kC2}, {kCra}); state()->pcc()->set_address(inst()->address()); // Set up the destination capability. c1_reg()->ResetExecuteRoot(); @@ -661,9 +665,9 @@ EXPECT_FALSE(trap_taken()) << "ec: " << std::hex << trap_exception_code() << " value: " << trap_value(); EXPECT_EQ(state()->pcc()->address(), inst()->address() + 0x200); - EXPECT_TRUE(c3_reg()->tag()); - EXPECT_TRUE(c3_reg()->IsSentry()); - EXPECT_EQ(c3_reg()->object_type(), OT::kInterruptDisablingSentry); + EXPECT_TRUE(cra_reg()->tag()); + EXPECT_TRUE(cra_reg()->IsSentry()); + EXPECT_EQ(cra_reg()->object_type(), OT::kInterruptDisablingReturnSentry); EXPECT_TRUE(state()->pcc()->tag()); // Set up the destination capability. c1_reg()->ResetExecuteRoot(); @@ -680,16 +684,16 @@ EXPECT_FALSE(trap_taken()) << "ec: " << std::hex << trap_exception_code() << " value: " << trap_value(); EXPECT_EQ(state()->pcc()->address(), inst()->address() + 0x200); - EXPECT_TRUE(c3_reg()->tag()); - EXPECT_TRUE(c3_reg()->IsSentry()); - EXPECT_EQ(c3_reg()->object_type(), OT::kInterruptEnablingSentry); + EXPECT_TRUE(cra_reg()->tag()); + EXPECT_TRUE(cra_reg()->IsSentry()); + EXPECT_EQ(cra_reg()->object_type(), OT::kInterruptEnablingReturnSentry); EXPECT_TRUE(state()->pcc()->tag()); } // Verify an unset tag generates a tag violation exception. TEST_F(RiscVCheriotInstructionsTest, CJalrTagViolation) { - inst()->set_semantic_function(&CheriotCJalr); - AppendCapabilityOperands(inst(), {kC1, kC2}, {kC3}); + inst()->set_semantic_function(&CheriotCJalrCra); + AppendCapabilityOperands(inst(), {kC1, kC2}, {kCra}); state()->pcc()->set_address(inst()->address()); // Set up the destination capability. c1_reg()->ResetExecuteRoot(); @@ -715,8 +719,8 @@ // For a jalr with a sentry, the immediate has to be zero or it will cause // an exception. Make sure the exception happens. TEST_F(RiscVCheriotInstructionsTest, CJalrSentryNonZeroImmediate) { - inst()->set_semantic_function(&CheriotCJalr); - AppendCapabilityOperands(inst(), {kC1, kC2}, {kC3}); + inst()->set_semantic_function(&CheriotCJalrCra); + AppendCapabilityOperands(inst(), {kC1, kC2}, {kCra}); state()->pcc()->set_address(inst()->address()); // Set up the destination capability. c1_reg()->ResetExecuteRoot(); @@ -742,8 +746,8 @@ // If the source capability does not have execute permission, there should // be an exception. TEST_F(RiscVCheriotInstructionsTest, CJalrExecuteViolation) { - inst()->set_semantic_function(&CheriotCJalr); - AppendCapabilityOperands(inst(), {kC1, kC2}, {kC3}); + inst()->set_semantic_function(&CheriotCJalrCra); + AppendCapabilityOperands(inst(), {kC1, kC2}, {kCra}); state()->pcc()->set_address(inst()->address()); // Set up the destination capability. c1_reg()->ResetExecuteRoot(); @@ -770,7 +774,7 @@ // If the architecture does not have compact instructions, then misaligned // access on two byte boundary should cause an exception. TEST_F(RiscVCheriotInstructionsTest, CJalrAlignmentViolation) { - inst()->set_semantic_function(&CheriotCJalr); + inst()->set_semantic_function(&CheriotCJalrCra); AppendCapabilityOperands(inst(), {kC1, kC2}, {kC3}); state()->pcc()->set_address(inst()->address()); // Set up the destination capability.
diff --git a/riscv_cheriot.bin_fmt b/riscv_cheriot.bin_fmt index 7ad4346..db6799c 100644 --- a/riscv_cheriot.bin_fmt +++ b/riscv_cheriot.bin_fmt
@@ -211,12 +211,22 @@ cheriot_gettype : R2Type : func7 == 0x7f, func5 == 0x01, func3 == 0, opcode == 0x5b; cheriot_incaddr : RType : func7 == 0x11, func3 == 0, opcode == 0x5b; cheriot_incaddrimm : IType : func3 == 0x1, opcode == 0x5b; - cheriot_jal : JType : rd != 0, opcode == 0x6f; - cheriot_j : JType : rd == 0, opcode == 0x6f; - cheriot_jalr : IType : func3 == 0x0, rd != 0, opcode == 0x67; - cheriot_jr : IType : func3 == 0x0, rd == 0, opcode == 0x67; - cheriot_lc : IType : func3 == 0x3, opcode == 0x03; - cheriot_move : RType : func7 == 0x7f, rs2 == 0xa, func3 == 0, opcode == 0x5b; + cheriot_jal : JType : rd != 0, opcode == 0x6f; + cheriot_j : JType : rd == 0, opcode == 0x6f; + // For jalr and jr, need to differentiate when the destination (jalr) or the + // source (jr) designates the cra register. + // Function call (dest != cra) (unsealed or interrupt inheriting forward sentry {0, 1}) + cheriot_jalr : IType : func3 == 0x0, rd > 1, opcode == 0x67; + // Function call (dest == cra) (unsealed or forward sentries {0, 1, 2, 3}). + cheriot_jalr_cra : IType : func3 == 0x0, rd == 1, opcode == 0x67; + // Tail call src != cra (unsealed or interrupt inheriting forward sentry {0, 1}) + cheriot_jr : IType : func3 == 0x0, rd == 0, rs1 > 1, opcode == 0x67; + // Function return src == cra (return sentries only {4, 5}) + cheriot_jr_cra : IType : func3 == 0x0, rd == 0, rs1 == 1, opcode == 0x67; + // Jalr causing exception: both rd and rs1 are 0. + cheriot_jalr_zero: IType : func3 == 0x0, rd == 0, rs1 == 0, opcode == 0x67; + cheriot_lc : IType : func3 == 0x3, opcode == 0x03; + cheriot_move : RType : func7 == 0x7f, rs2 == 0xa, func3 == 0, opcode == 0x5b; cheriot_representablealignmentmask : R2Type : func7 == 0x7f, func5 == 0x9, func3 == 0, opcode == 0x5b; cheriot_roundrepresentablelength : R2Type : func7 == 0x7f, func5 == 0x8, func3 == 0, opcode == 0x5b; cheriot_sc : SType : func3 == 0x3, opcode == 0x23; @@ -255,33 +265,6 @@ amomaxw : AType : func5 == 0b1'0100, func3 == 0b010, opcode == 0b010'1111; amominuw : AType : func5 == 0b1'1000, func3 == 0b010, opcode == 0b010'1111; amomaxuw : AType : func5 == 0b1'1100, func3 == 0b010, opcode == 0b010'1111; - // RiscV32 single precision floating point instructions. - flw : IType : func3 == 0b010, opcode == 0b000'0111; - fsw : SType : func3 == 0b010, opcode == 0b010'0111; - fmadd_s : R4Type : func2 == 0b00, opcode == 0b100'0011; - fmsub_s : R4Type : func2 == 0b00, opcode == 0b100'0111; - fnmsub_s : R4Type : func2 == 0b00, opcode == 0b100'1011; - fnmadd_s : R4Type : func2 == 0b00, opcode == 0b100'1111; - fadd_s : RType : func7 == 0b000'0000, opcode == 0b101'0011; - fsub_s : RType : func7 == 0b000'0100, opcode == 0b101'0011; - fmul_s : RType : func7 == 0b000'1000, opcode == 0b101'0011; - fdiv_s : RType : func7 == 0b000'1100, opcode == 0b101'0011; - fsqrt_s : R2Type : func7 == 0b010'1100, func5 == 0, opcode == 0b101'0011; - fsgnj_s : RType : func7 == 0b001'0000, func3 == 0b000, opcode == 0b101'0011; - fsgnjn_s : RType : func7 == 0b001'0000, func3 == 0b001, opcode == 0b101'0011; - fsgnjx_s : RType : func7 == 0b001'0000, func3 == 0b010, opcode == 0b101'0011; - fmin_s : RType : func7 == 0b001'0100, func3 == 0b000, opcode == 0b101'0011; - fmax_s : RType : func7 == 0b001'0100, func3 == 0b001, opcode == 0b101'0011; - fcvt_ws : R2Type : func7 == 0b110'0000, func5 == 0, opcode == 0b101'0011; - fcvt_wus : R2Type : func7 == 0b110'0000, func5 == 1, opcode == 0b101'0011; - fmv_xw : R2Type : func7 == 0b111'0000, func5 == 0, func3 == 0b000, opcode == 0b101'0011; - fcmpeq_s : RType : func7 == 0b101'0000, func3 == 0b010, opcode == 0b101'0011; - fcmplt_s : RType : func7 == 0b101'0000, func3 == 0b001, opcode == 0b101'0011; - fcmple_s : RType : func7 == 0b101'0000, func3 == 0b000, opcode == 0b101'0011; - fclass_s : R2Type : func7 == 0b111'0000, func5 == 0, func3 == 0b001, opcode == 0b101'0011; - fcvt_sw : R2Type : func7 == 0b110'1000, func5 == 0, opcode == 0b101'0011; - fcvt_swu : R2Type : func7 == 0b110'1000, func5 == 1, opcode == 0b101'0011; - fmv_wx : R2Type : func7 == 0b111'1000, func5 == 0, func3 == 0b000, opcode == 0b101'0011; // RiscV32 CSR manipulation instructions. csrrw : IType : func3 == 0b001, rd != 0, opcode == 0b111'0011; csrrs : IType : func3 == 0b010, rs1 != 0, rd != 0, opcode == 0b111'0011; @@ -456,15 +439,21 @@ csw : CS : func3 == 0b110, op == 0b00; csd : CS : func3 == 0b111, op == 0b00; cnop : CI : func3 == 0b000, imm1 == 0, rs1 == 0, imm5 == 0, op == 0b01; + chint : CI : func3 == 0b000, imm6 != 0, rs1 == 0, op == 0b01; caddi : CI : func3 == 0b000, imm6 != 0, rd != 0, op == 0b01; + chint : CI : func3 == 0b000, imm6 == 0, rd != 0, op == 0b01; cli : CI : func3 == 0b010, rd != 0, op == 0b01; + chint : CI : func3 == 0b010, rd == 0, op == 0b01; caddi16sp : CI : func3 == 0b011, ci_imm10 != 0, rd == 2, op == 0b01; clui : CI : func3 == 0b011, rd != 0, rd != 2, imm18 != 0, op == 0b01; + chint : CI : func3 == 0b011, rd == 0, imm18 != 0, op == 0b01; // TODO(torerik): The following two instructions should have imm1 == 0 and // imm5 != 0 instead of imm6 != 0 in the constraints, but that has been // temporarily removed so as to make it easier to verify in TestRIG csrli : CSH : func3 == 0b100, op2 == 0b00, uimm6 != 0, op == 0b01; + chint : CSH : func3 == 0b100, op2 == 0b00, uimm6 == 0, op == 0b01; csrai : CSH : func3 == 0b100, op2 == 0b01, uimm6 != 0, op == 0b01; + chint : CSH : func3 == 0b100, op2 == 0b01, uimm6 == 0, op == 0b01; candi : CSH : func3 == 0b100, op2 == 0b10, op == 0b01; csub : CA : func6 == 0b100'011, func2 == 0b00, op == 0b01; cxor : CA : func6 == 0b100'011, func2 == 0b01, op == 0b01; @@ -473,15 +462,19 @@ cbeqz : CB : func3 == 0b110, op == 0b01; cbnez : CB : func3 == 0b111, op == 0b01; cslli : CI : func3 == 0b000, imm1 == 0, imm5 != 0, rs1 != 0, op == 0b10; + chint : CI : func3 == 0b000, imm1 == 0, rs1 == 0, imm5 != 0, op == 0b10; + chint : CI : func3 == 0b000, imm6 == 0, op == 0b10; clwsp : CI : func3 == 0b010, rd != 0, op == 0b10; cldsp : CI : func3 == 0b011, rd != 0, op == 0b10; cmv : CR : func4 == 0b1000, rs1 != 0, rs2 != 0, op == 0b10; cebreak : Inst16Format : func3 == 0b100, bits == 0b1'00000'00000, op == 0b10; cadd : CR : func4 == 0b1001, rs1 != 0, rs2 != 0, op == 0b10; + chint : CR : func4 == 0b1001, rs1 == 0, rs2 != 0, op == 0b10; cswsp : CSS: func3 == 0b110, op == 0b10; csdsp : CSS: func3 == 0b111, op == 0b10; - cheriot_cj : CJ : func3 == 0b101, op == 0b01; - cheriot_cjal : CJ : func3 == 0b001, op == 0b01; - cheriot_cjr : CR : func4 == 0b1000, rs1 != 0, rs2 == 0, op == 0b10; - cheriot_cjalr : CR : func4 == 0b1001, rs1 != 0, rs2 == 0, op == 0b10; + cheriot_cj : CJ : func3 == 0b101, op == 0b01; + cheriot_cjal : CJ : func3 == 0b001, op == 0b01; + cheriot_cjr : CR : func4 == 0b1000, rs1 > 1, rs2 == 0, op == 0b10; + cheriot_cjr_cra : CR : func4 == 0b1000, rs1 == 1, rs2 == 0, op == 0b10; + cheriot_cjalr_cra : CR : func4 == 0b1001, rs1 != 0, rs2 == 0, op == 0b10; };
diff --git a/riscv_cheriot.isa b/riscv_cheriot.isa index 28fec73..5e0386b 100644 --- a/riscv_cheriot.isa +++ b/riscv_cheriot.isa
@@ -200,9 +200,18 @@ cheriot_jalr{: cs1, J_imm12 : cd}, disasm: "cjalr", "%cd, %cs1, 0x%(J_imm12:08x)", semfunc: "&CheriotCJalr"; + cheriot_jalr_cra{: cs1, J_imm12 : cd}, + disasm: "cjalr", "%cd, %cs1, 0x%(J_imm12:08x)", + semfunc: "&CheriotCJalrCra"; cheriot_jr{: cs1, J_imm12 : }, disasm: "cjalr", "%cs1, 0x%(J_imm12:08x)", semfunc: "&CheriotCJr"; + cheriot_jr_cra{: cs1, J_imm12 : }, + disasm: "cjalr", "%cs1, 0x%(J_imm12:08x)", + semfunc: "&CheriotCJrCra"; + cheriot_jalr_zero{: cs1 :}, + disasm: "cjalr", "czero, czero, 0", + semfunc: "&CheriotCJalrZero"; cheriot_lc{(: cs1, I_imm12 :),(: : cd)}, disasm: "clc", "%cd, %cs1, 0x%(I_imm12:08x)", semfunc: "&CheriotCLc", "&CheriotCLcChild"; @@ -442,95 +451,6 @@ } } -// RiscV32 F (single precision floating point) instructions. -slot riscv32f { - includes { - #include "cheriot/riscv_cheriot_f_instructions.h" - } - default size = 4; - default latency = global_latency; - opcodes { - flw{(: rs1, I_imm12 : ), (: : frd)}, - semfunc: "&RiscVILw", "&RiscVIFlwChild", - disasm: "flw", "%frd, %I_imm12(%rs1)"; - fsw{: rs1, S_imm12, frs2}, - semfunc: "&RiscVFSw", - disasm: "fsw", "%frs2, %S_imm12(%rs1)"; - fadd_s{: frs1, frs2, rm : frd}, - semfunc: "&RiscVFAdd", - disasm: "fadd", "%frd, %frs1, %frs2"; - fsub_s{: frs1, frs2, rm : frd}, - semfunc: "&RiscVFSub", - disasm: "fsub", "%frd, %frs1, %frs2"; - fmul_s{: frs1, frs2, rm : frd}, - semfunc: "&RiscVFMul", - disasm: "fmul", "%frd, %frs1, %frs2"; - fdiv_s{: frs1, frs2, rm : frd}, - semfunc: "&RiscVFDiv", - disasm: "fdiv", "%frd, %frs1, %frs2"; - fsqrt_s{: frs1, rm : frd}, - semfunc: "&RiscVFSqrt", - disasm: "fsqrt", "%frd, %frs1"; - fmin_s{: frs1, frs2 : frd, fflags}, - semfunc: "&RiscVFMin", - disasm: "fmin", "%frd, %frs1, %frs2"; - fmax_s{: frs1, frs2 : frd, fflags}, - semfunc: "&RiscVFMax", - disasm: "fmax", "%frd, %frs1, %frs2"; - fmadd_s{: frs1, frs2, frs3, rm : frd, fflags}, - semfunc: "&RiscVFMadd", - disasm: "fmadd", "%frd, %frs1, %frs2, %frs3"; - fmsub_s{: frs1, frs2, frs3, rm : frd, fflags}, - semfunc: "&RiscVFMsub", - disasm: "fmsub", "%frd, %frs1, %frs2, %frs3"; - fnmadd_s{: frs1, frs2, frs3, rm : frd, fflags}, - semfunc: "&RiscVFNmadd", - disasm: "fnmadd", "%frd, %frs1, %frs2, %frs3"; - fnmsub_s{: frs1, frs2, frs3, rm : frd, fflags}, - semfunc: "&RiscVFNmsub", - disasm: "fnmsub", "%frd, %frs1, %frs2, %frs3"; - fcvt_ws{: frs1, rm : rd, fflags}, - semfunc: "&RiscVFCvtWs", - disasm: "fcvt.w.s", "%rd, %frs1"; - fcvt_sw{: rs1, rm : frd}, - semfunc: "&RiscVFCvtSw", - disasm: "fcvt.s.w", "%frd, %rs1"; - fcvt_wus{: frs1, rm : rd, fflags}, - semfunc: "&RiscVFCvtWus", - disasm: "fcvt.wu.s", "%rd, %frs1"; - fcvt_swu{: rs1, rm : frd}, - semfunc: "&RiscVFCvtSwu", - disasm: "fcvt.s.wu", "%frd, %rs1"; - fsgnj_s{: frs1, frs2 : frd}, - semfunc: "&RiscVFSgnj", - disasm: "fsgn.s", "%frd, %frs1, %frs2"; - fsgnjn_s{: frs1, frs2 : frd}, - semfunc: "&RiscVFSgnjn", - disasm: "fsgnjx.s", "%frd, %frs1, %frs2"; - fsgnjx_s{: frs1, frs2 : frd}, - semfunc: "&RiscVFSgnjx", - disasm: "fsgnjx.s", "%frd, %frs1, %frs2"; - fmv_xw{: frs1 : rd}, - disasm: "mv.x.w", "%rd, %frs1", - semfunc: "&RiscVFMvxw"; - fmv_wx{: rs1 : frd}, - disasm: "mv.w.x", "%frd, %rs1", - semfunc: "&RiscVFMvwx"; - fcmpeq_s{: frs1, frs2 : rd, fflags}, - semfunc: "&RiscVFCmpeq", - disasm: "fcmpeq", "%rd, %frs1, %frs2"; - fcmplt_s{: frs1, frs2 : rd, fflags}, - semfunc: "&RiscVFCmplt", - disasm: "fcmplt", "%rd, %frs1, %frs2"; - fcmple_s{: frs1, frs2 : rd, fflags}, - semfunc: "&RiscVFCmple", - disasm: "fcmple", "%rd, %frs1, %frs2"; - fclass_s{: frs1 : rd}, - semfunc: "&RiscVFClass", - disasm: "fclass", "%rd, %frs1"; - } -} - // RISCV32 C (compact instructions). slot riscv32c { default size = 2; @@ -591,9 +511,12 @@ cheriot_cjr{: crs1, x0 :}, disasm: "c.jr", "%crs1", semfunc: "&CheriotCJr"; - cheriot_cjalr{: crs1, x0 : x1}, + cheriot_cjr_cra{: crs1, x0 :}, + disasm: "c.jr", "%crs1", + semfunc: "&CheriotCJrCra"; + cheriot_cjalr_cra{: crs1, x0 : x1}, disasm: "c.jalr", "%crs1", - semfunc: "&CheriotCJalr"; + semfunc: "&CheriotCJalrCra"; cbeqz{: c3rs1, x0, I_cb_imm8 : }, disasm: "c.beqz", "%c3rs1, %(@+I_cb_imm8:08x)", semfunc: "&RiscVIBeq"; @@ -649,6 +572,9 @@ cnop{}, disasm: "c.nop", semfunc: "&RiscVINop"; + chint{}, + disasm: "c.hint", + semfunc: "&RiscVINop"; cebreak{}, disasm: "c.ebreak", semfunc: "&RiscVIEbreak"; @@ -657,7 +583,7 @@ // This should be the RiscV32 CHERIoT set. slot riscv32_cheriot : riscv32i, cheriot, riscv32_amo_arithmetic, riscv32c, - riscv32m, riscv32f, zicsr, privileged { + riscv32m, zicsr, privileged { default size = 4; default opcode = disasm: "Illegal instruction at 0x%(@:08x)",