• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef BERBERIS_DECODER_RISCV64_SEMANTICS_PLAYER_H_
18 #define BERBERIS_DECODER_RISCV64_SEMANTICS_PLAYER_H_
19 
20 #include "berberis/base/overloaded.h"
21 #include "berberis/decoder/riscv64/decoder.h"
22 
23 namespace berberis {
24 
25 // This class expresses the semantics of instructions by calling a sequence of SemanticsListener
26 // callbacks.
27 template <class SemanticsListener>
28 class SemanticsPlayer {
29  public:
30   using Decoder = Decoder<SemanticsPlayer>;
31   using Register = typename SemanticsListener::Register;
32   using FpRegister = typename SemanticsListener::FpRegister;
33 
SemanticsPlayer(SemanticsListener * listener)34   explicit SemanticsPlayer(SemanticsListener* listener) : listener_(listener) {}
35 
36   // Decoder's InsnConsumer implementation.
37 
Csr(const typename Decoder::CsrArgs & args)38   void Csr(const typename Decoder::CsrArgs& args) {
39     Register result;
40     Register arg = GetRegOrZero(args.src);
41     result = listener_->Csr(args.opcode, arg, args.csr);
42     SetRegOrIgnore(args.dst, result);
43   }
44 
Csr(const typename Decoder::CsrImmArgs & args)45   void Csr(const typename Decoder::CsrImmArgs& args) {
46     Register result;
47     result = listener_->Csr(args.opcode, args.imm, args.csr);
48     SetRegOrIgnore(args.dst, result);
49   }
50 
Fence(const typename Decoder::FenceArgs & args)51   void Fence(const typename Decoder::FenceArgs& args) {
52     listener_->Fence(args.opcode,
53                      args.src,
54                      args.sw,
55                      args.sr,
56                      args.so,
57                      args.si,
58                      args.pw,
59                      args.pr,
60                      args.po,
61                      args.pi);
62     // The unused fields in the FENCE instructions — args.src and args.dst — are reserved for
63     // finer-grain fences in future extensions. For forward compatibility, base implementations
64     // shall ignore these fields, and standard software shall zero these fields. Likewise, many
65     // args.opcode and predecessor/successor set settings are also reserved for future use. Base
66     // implementations shall treat all such reserved configurations as normal fences with
67     // args.opcode=0000, and standard software shall use only non-reserved configurations.
68   }
69 
FenceI(const typename Decoder::FenceIArgs & args)70   void FenceI(const typename Decoder::FenceIArgs& args) {
71     Register arg = GetRegOrZero(args.src);
72     listener_->FenceI(arg, args.imm);
73     // The unused fields in the FENCE.I instruction, imm[11:0], rs1, and rd, are reserved for
74     // finer-grain fences in future extensions. For forward compatibility, base implementations
75     // shall ignore these fields, and standard software shall zero these fields.
76   }
77 
78   template <typename OpArgs>
Op(OpArgs && args)79   void Op(OpArgs&& args) {
80     Register arg1 = GetRegOrZero(args.src1);
81     Register arg2 = GetRegOrZero(args.src2);
82     Register result = Overloaded{[&](const typename Decoder::OpArgs& args) {
83                                    return listener_->Op(args.opcode, arg1, arg2);
84                                  },
85                                  [&](const typename Decoder::Op32Args& args) {
86                                    return listener_->Op32(args.opcode, arg1, arg2);
87                                  }}(args);
88     SetRegOrIgnore(args.dst, result);
89   };
90 
Amo(const typename Decoder::AmoArgs & args)91   void Amo(const typename Decoder::AmoArgs& args) {
92     Register arg1 = GetRegOrZero(args.src1);
93     Register arg2 = GetRegOrZero(args.src2);
94     Register result = listener_->Amo(args.opcode, arg1, arg2, args.aq, args.rl);
95     SetRegOrIgnore(args.dst, result);
96   };
97 
Lui(const typename Decoder::UpperImmArgs & args)98   void Lui(const typename Decoder::UpperImmArgs& args) {
99     Register result = listener_->Lui(args.imm);
100     SetRegOrIgnore(args.dst, result);
101   }
102 
Auipc(const typename Decoder::UpperImmArgs & args)103   void Auipc(const typename Decoder::UpperImmArgs& args) {
104     Register result = listener_->Auipc(args.imm);
105     SetRegOrIgnore(args.dst, result);
106   }
107 
Load(const typename Decoder::LoadArgs & args)108   void Load(const typename Decoder::LoadArgs& args) {
109     Register arg = GetRegOrZero(args.src);
110     Register result = listener_->Load(args.opcode, arg, args.offset);
111     SetRegOrIgnore(args.dst, result);
112   };
113 
Load(const typename Decoder::LoadFpArgs & args)114   void Load(const typename Decoder::LoadFpArgs& args) {
115     Register arg = GetRegOrZero(args.src);
116     FpRegister result = listener_->LoadFp(args.opcode, arg, args.offset);
117     SetFpReg(args.dst, result);
118   };
119 
120   template <typename OpImmArgs>
OpImm(OpImmArgs && args)121   void OpImm(OpImmArgs&& args) {
122     Register arg = GetRegOrZero(args.src);
123     Register result = Overloaded{[&](const typename Decoder::OpImmArgs& args) {
124                                    return listener_->OpImm(args.opcode, arg, args.imm);
125                                  },
126                                  [&](const typename Decoder::OpImm32Args& args) {
127                                    return listener_->OpImm32(args.opcode, arg, args.imm);
128                                  },
129                                  [&](const typename Decoder::ShiftImmArgs& args) {
130                                    return listener_->ShiftImm(args.opcode, arg, args.imm);
131                                  },
132                                  [&](const typename Decoder::ShiftImm32Args& args) {
133                                    return listener_->ShiftImm32(args.opcode, arg, args.imm);
134                                  }}(args);
135     SetRegOrIgnore(args.dst, result);
136   };
137 
OpFp(const typename Decoder::OpFpArgs & args)138   void OpFp(const typename Decoder::OpFpArgs& args) {
139     FpRegister arg1 = GetFpReg(args.src1);
140     FpRegister arg2 = GetFpReg(args.src2);
141     FpRegister result = listener_->OpFp(args.opcode, args.float_size, args.rm, arg1, arg2);
142     SetFpReg(args.dst, result);
143   }
144 
Store(const typename Decoder::StoreArgs & args)145   void Store(const typename Decoder::StoreArgs& args) {
146     Register arg = GetRegOrZero(args.src);
147     Register data = GetRegOrZero(args.data);
148     listener_->Store(args.opcode, arg, args.offset, data);
149   };
150 
Store(const typename Decoder::StoreFpArgs & args)151   void Store(const typename Decoder::StoreFpArgs& args) {
152     Register arg = GetRegOrZero(args.src);
153     FpRegister data = GetFpReg(args.data);
154     listener_->StoreFp(args.opcode, arg, args.offset, data);
155   };
156 
Branch(const typename Decoder::BranchArgs & args)157   void Branch(const typename Decoder::BranchArgs& args) {
158     Register arg1 = GetRegOrZero(args.src1);
159     Register arg2 = GetRegOrZero(args.src2);
160     listener_->Branch(args.opcode, arg1, arg2, args.offset);
161   };
162 
JumpAndLink(const typename Decoder::JumpAndLinkArgs & args)163   void JumpAndLink(const typename Decoder::JumpAndLinkArgs& args) {
164     Register result = listener_->JumpAndLink(args.offset, args.insn_len);
165     SetRegOrIgnore(args.dst, result);
166   };
167 
JumpAndLinkRegister(const typename Decoder::JumpAndLinkRegisterArgs & args)168   void JumpAndLinkRegister(const typename Decoder::JumpAndLinkRegisterArgs& args) {
169     Register base = GetRegOrZero(args.base);
170     Register result = listener_->JumpAndLinkRegister(base, args.offset, args.insn_len);
171     SetRegOrIgnore(args.dst, result);
172   };
173 
174   // We may have executed a signal handler just after the syscall. If that handler changed x10, then
175   // overwriting x10 here would be incorrect. On the other hand asynchronous signals are unlikely to
176   // change CPU state, so we don't support this at the moment for simplicity."
System(const typename Decoder::SystemArgs & args)177   void System(const typename Decoder::SystemArgs& args) {
178     if (args.opcode != Decoder::SystemOpcode::kEcall) {
179       return Unimplemented();
180     }
181     Register syscall_nr = GetRegOrZero(17);
182     Register arg0 = GetRegOrZero(10);
183     Register arg1 = GetRegOrZero(11);
184     Register arg2 = GetRegOrZero(12);
185     Register arg3 = GetRegOrZero(13);
186     Register arg4 = GetRegOrZero(14);
187     Register arg5 = GetRegOrZero(15);
188     Register result = listener_->Ecall(syscall_nr, arg0, arg1, arg2, arg3, arg4, arg5);
189     SetRegOrIgnore(10, result);
190   }
191 
Nop()192   void Nop() { listener_->Nop(); }
193 
Unimplemented()194   void Unimplemented() { listener_->Unimplemented(); };
195 
196  private:
GetRegOrZero(uint8_t reg)197   Register GetRegOrZero(uint8_t reg) {
198     return reg == 0 ? listener_->GetImm(0) : listener_->GetReg(reg);
199   }
200 
SetRegOrIgnore(uint8_t reg,Register value)201   void SetRegOrIgnore(uint8_t reg, Register value) {
202     if (reg != 0) {
203       listener_->SetReg(reg, value);
204     }
205   }
206 
GetFpReg(uint8_t reg)207   FpRegister GetFpReg(uint8_t reg) { return listener_->GetFpReg(reg); }
208 
SetFpReg(uint8_t reg,FpRegister value)209   void SetFpReg(uint8_t reg, FpRegister value) { listener_->SetFpReg(reg, value); }
210 
211   SemanticsListener* listener_;
212 };
213 
214 }  // namespace berberis
215 
216 #endif  // BERBERIS_DECODER_RISCV64_SEMANTICS_PLAYER_H_
217