arch-riscv: Move standard ops out of ISA
[gem5.git] / src / arch / riscv / isa / formats / standard.isa
1 // -*- mode:c++ -*-
2
3 // Copyright (c) 2015 RISC-V Foundation
4 // Copyright (c) 2016-2017 The University of Virginia
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are
9 // met: redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer;
11 // redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution;
14 // neither the name of the copyright holders nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Authors: Alec Roelke
31
32 ////////////////////////////////////////////////////////////////////
33 //
34 // Integer instructions
35 //
36
37 def template ImmDeclare {{
38 //
39 // Static instruction class for "%(mnemonic)s".
40 //
41 class %(class_name)s : public %(base_class)s
42 {
43 public:
44 /// Constructor.
45 %(class_name)s(MachInst machInst);
46 Fault execute(ExecContext *, Trace::InstRecord *) const;
47 std::string generateDisassembly(Addr pc,
48 const SymbolTable *symtab) const override;
49 };
50 }};
51
52 def template ImmConstructor {{
53 %(class_name)s::%(class_name)s(MachInst machInst)
54 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
55 {
56 %(constructor)s;
57 %(imm_code)s;
58 }
59 }};
60
61 def template ImmExecute {{
62 Fault
63 %(class_name)s::execute(
64 ExecContext *xc, Trace::InstRecord *traceData) const
65 {
66 Fault fault = NoFault;
67
68 %(op_decl)s;
69 %(op_rd)s;
70 if (fault == NoFault) {
71 %(code)s;
72 if (fault == NoFault) {
73 %(op_wb)s;
74 }
75 }
76 return fault;
77 }
78
79 std::string
80 %(class_name)s::generateDisassembly(Addr pc,
81 const SymbolTable *symtab) const
82 {
83 std::vector<RegId> indices = {%(regs)s};
84 std::stringstream ss;
85 ss << mnemonic << ' ';
86 for (const RegId& idx: indices)
87 ss << registerName(idx) << ", ";
88 ss << imm;
89 return ss.str();
90 }
91 }};
92
93 def template BranchDeclare {{
94 //
95 // Static instruction class for "%(mnemonic)s".
96 //
97 class %(class_name)s : public %(base_class)s
98 {
99 public:
100 /// Constructor.
101 %(class_name)s(MachInst machInst);
102 Fault execute(ExecContext *, Trace::InstRecord *) const;
103
104 std::string
105 generateDisassembly(Addr pc, const SymbolTable *symtab) const override;
106
107 RiscvISA::PCState
108 branchTarget(const RiscvISA::PCState &branchPC) const override;
109
110 using StaticInst::branchTarget;
111 };
112 }};
113
114 def template BranchExecute {{
115 Fault
116 %(class_name)s::execute(ExecContext *xc,
117 Trace::InstRecord *traceData) const
118 {
119 Fault fault = NoFault;
120
121 %(op_decl)s;
122 %(op_rd)s;
123 if (fault == NoFault) {
124 %(code)s;
125 if (fault == NoFault) {
126 %(op_wb)s;
127 }
128 }
129 return fault;
130 }
131
132 RiscvISA::PCState
133 %(class_name)s::branchTarget(const RiscvISA::PCState &branchPC) const
134 {
135 return branchPC.pc() + imm;
136 }
137
138 std::string
139 %(class_name)s::generateDisassembly(Addr pc,
140 const SymbolTable *symtab) const
141 {
142 std::vector<RegId> indices = {%(regs)s};
143 std::stringstream ss;
144 ss << mnemonic << ' ';
145 for (const RegId& idx: indices)
146 ss << registerName(idx) << ", ";
147 ss << imm;
148 return ss.str();
149 }
150 }};
151
152 def template JumpDeclare {{
153 //
154 // Static instruction class for "%(mnemonic)s".
155 //
156 class %(class_name)s : public %(base_class)s
157 {
158 public:
159 /// Constructor.
160 %(class_name)s(MachInst machInst);
161 Fault execute(ExecContext *, Trace::InstRecord *) const;
162
163 std::string
164 generateDisassembly(Addr pc, const SymbolTable *symtab) const override;
165
166 RiscvISA::PCState
167 branchTarget(ThreadContext *tc) const override;
168
169 using StaticInst::branchTarget;
170 };
171 }};
172
173 def template JumpExecute {{
174 Fault
175 %(class_name)s::execute(
176 ExecContext *xc, Trace::InstRecord *traceData) const
177 {
178 Fault fault = NoFault;
179
180 %(op_decl)s;
181 %(op_rd)s;
182 if (fault == NoFault) {
183 %(code)s;
184 if (fault == NoFault) {
185 %(op_wb)s;
186 }
187 }
188 return fault;
189 }
190
191 RiscvISA::PCState
192 %(class_name)s::branchTarget(ThreadContext *tc) const
193 {
194 PCState pc = tc->pcState();
195 pc.set((tc->readIntReg(_srcRegIdx[0].index()) + imm)&~0x1);
196 return pc;
197 }
198
199 std::string
200 %(class_name)s::generateDisassembly(Addr pc,
201 const SymbolTable *symtab) const
202 {
203 std::vector<RegId> indices = {%(regs)s};
204 std::stringstream ss;
205 ss << mnemonic << ' ';
206 for (const RegId& idx: indices)
207 ss << registerName(idx) << ", ";
208 ss << imm;
209 return ss.str();
210 }
211 }};
212
213 def format ROp(code, *opt_flags) {{
214 iop = InstObjParams(name, Name, 'RegOp', code, opt_flags)
215 header_output = BasicDeclare.subst(iop)
216 decoder_output = BasicConstructor.subst(iop)
217 decode_block = BasicDecode.subst(iop)
218 exec_output = BasicExecute.subst(iop)
219 }};
220
221 def format IOp(code, *opt_flags) {{
222 imm_code = 'imm = IMM12; if (IMMSIGN > 0) imm |= ~((uint64_t)0x7FF);'
223 regs = ['_destRegIdx[0]','_srcRegIdx[0]']
224 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
225 {'code': code, 'imm_code': imm_code,
226 'regs': ','.join(regs)}, opt_flags)
227 header_output = ImmDeclare.subst(iop)
228 decoder_output = ImmConstructor.subst(iop)
229 decode_block = BasicDecode.subst(iop)
230 exec_output = ImmExecute.subst(iop)
231 }};
232
233 def format BOp(code, *opt_flags) {{
234 imm_code = """
235 imm |= BIMM12BIT11 << 11;
236 imm |= BIMM12BITS4TO1 << 1;
237 imm |= BIMM12BITS10TO5 << 5;
238 if (IMMSIGN > 0)
239 imm |= ~((uint64_t)0xFFF);
240 """
241 regs = ['_srcRegIdx[0]','_srcRegIdx[1]']
242 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
243 {'code': code, 'imm_code': imm_code,
244 'regs': ','.join(regs)}, opt_flags)
245 header_output = BranchDeclare.subst(iop)
246 decoder_output = ImmConstructor.subst(iop)
247 decode_block = BasicDecode.subst(iop)
248 exec_output = BranchExecute.subst(iop)
249 }};
250
251 def format Jump(code, *opt_flags) {{
252 imm_code = 'imm = IMM12; if (IMMSIGN > 0) imm |= ~((uint64_t)0x7FF);'
253 regs = ['_destRegIdx[0]','_srcRegIdx[0]']
254 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
255 {'code': code, 'imm_code': imm_code,
256 'regs': ','.join(regs)}, opt_flags)
257 header_output = JumpDeclare.subst(iop)
258 decoder_output = ImmConstructor.subst(iop)
259 decode_block = BasicDecode.subst(iop)
260 exec_output = JumpExecute.subst(iop)
261 }};
262
263 def format UOp(code, *opt_flags) {{
264 imm_code = 'imm = (int32_t)(IMM20 << 12);'
265 regs = ['_destRegIdx[0]']
266 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
267 {'code': code, 'imm_code': imm_code,
268 'regs': ','.join(regs)}, opt_flags)
269 header_output = ImmDeclare.subst(iop)
270 decoder_output = ImmConstructor.subst(iop)
271 decode_block = BasicDecode.subst(iop)
272 exec_output = ImmExecute.subst(iop)
273 }};
274
275 def format JOp(code, *opt_flags) {{
276 imm_code = """
277 imm |= UJIMMBITS19TO12 << 12;
278 imm |= UJIMMBIT11 << 11;
279 imm |= UJIMMBITS10TO1 << 1;
280 if (IMMSIGN > 0)
281 imm |= ~((uint64_t)0xFFFFF);
282 """
283 pc = 'pc.set(pc.pc() + imm);'
284 regs = ['_destRegIdx[0]']
285 iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
286 {'code': code, 'imm_code': imm_code,
287 'regs': ','.join(regs)}, opt_flags)
288 header_output = BranchDeclare.subst(iop)
289 decoder_output = ImmConstructor.subst(iop)
290 decode_block = BasicDecode.subst(iop)
291 exec_output = BranchExecute.subst(iop)
292 }};
293
294 def format SystemOp(code, *opt_flags) {{
295 iop = InstObjParams(name, Name, 'SystemOp', code, opt_flags)
296 header_output = BasicDeclare.subst(iop)
297 decoder_output = BasicConstructor.subst(iop)
298 decode_block = BasicDecode.subst(iop)
299 exec_output = BasicExecute.subst(iop)
300 }};
301
302 def format CSROp(code, *opt_flags) {{
303 iop = InstObjParams(name, Name, 'CSROp', code, opt_flags)
304 header_output = BasicDeclare.subst(iop)
305 decoder_output = BasicConstructor.subst(iop)
306 decode_block = BasicDecode.subst(iop)
307 exec_output = BasicExecute.subst(iop)
308 }};