/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "berberis/guest_state/guest_state.h" #include "berberis/base/checks.h" #include "berberis/guest_state/guest_state_arch.h" #include "berberis/guest_state/guest_state_opaque.h" namespace berberis { void SetReturnValueRegister(CPUState& cpu, GuestAddr val) { SetXReg<A0>(cpu, val); } GuestAddr GetReturnValueRegister(const CPUState& cpu) { return GetXReg<A0>(cpu); } void SetStackRegister(CPUState& cpu, GuestAddr val) { SetXReg<SP>(cpu, val); } GuestAddr GetStackRegister(const CPUState& cpu) { return GetXReg<SP>(cpu); } void SetLinkRegister(CPUState& cpu, GuestAddr val) { SetXReg<RA>(cpu, val); } GuestAddr GetLinkRegister(const CPUState& cpu) { return GetXReg<RA>(cpu); } void SetTlsAddr(ThreadState& state, GuestAddr addr) { SetXReg<TP>(state.cpu, addr); } GuestAddr GetTlsAddr(const ThreadState& state) { return GetXReg<TP>(state.cpu); } void SetShadowCallStackPointer(CPUState& cpu, GuestAddr scs_sp) { SetXReg<GP>(cpu, scs_sp); } void AdvanceInsnAddrBeyondSyscall(CPUState& cpu) { // RV64I uses the same 4-byte ECALL instruction as RV32I. // See ratified RISC-V unprivileged spec v2.1. cpu.insn_addr += 4; } std::size_t GetThreadStateRegOffset(int reg) { return offsetof(ThreadState, cpu.x[reg]); } std::size_t GetThreadStateFRegOffset(int freg) { return offsetof(ThreadState, cpu.f[freg]); } std::size_t GetThreadStateVRegOffset(int vreg) { return offsetof(ThreadState, cpu.v[vreg]); } std::size_t GetThreadStateSimdRegOffset(int /* simd_reg */) { // RISCV64 does not have simd registers. UNREACHABLE(); } std::size_t GetThreadStateReservationAddressOffset() { return offsetof(ThreadState, cpu.reservation_address); } std::size_t GetThreadStateReservationValueOffset() { return offsetof(ThreadState, cpu.reservation_value); } bool IsSimdOffset(size_t offset) { size_t v0_offset = offsetof(ThreadState, cpu.v); return (offset >= v0_offset) && ((offset - v0_offset) < sizeof(ThreadState::cpu.v)); } bool DoesCpuStateHaveFlags() { return false; } bool DoesCpuStateHaveDedicatedFpRegs() { return true; } bool DoesCpuStateHaveDedicatedVecRegs() { return true; } bool DoesCpuStateHaveDedicatedSimdRegs() { return false; } std::size_t GetThreadStateFlagOffset() { // RISCV64 Does not have flags in its CPUState CHECK(false); } } // namespace berberis