standard.isa revision 12234:78ece221f9f5
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//
36output header {{
37    /**
38     * Base class for operations that work only on registers
39     */
40    class RegOp : public RiscvStaticInst
41    {
42      protected:
43        /// Constructor
44        RegOp(const char *mnem, MachInst _machInst, OpClass __opClass)
45            : RiscvStaticInst(mnem, _machInst, __opClass)
46        {}
47
48        std::string
49        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
50    };
51
52    /**
53     * Base class for operations with signed immediates
54     */
55    class ImmOp : public RiscvStaticInst
56    {
57      protected:
58        int64_t imm;
59
60        /// Constructor
61        ImmOp(const char *mnem, MachInst _machInst, OpClass __opClass)
62            : RiscvStaticInst(mnem, _machInst, __opClass), imm(0)
63        {}
64
65        virtual std::string
66        generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
67    };
68
69    /**
70     * Base class for operations with unsigned immediates
71     */
72    class UImmOp : public RiscvStaticInst
73    {
74      protected:
75        uint64_t imm;
76
77        /// Constructor
78        UImmOp(const char *mnem, MachInst _machInst, OpClass __opClass)
79            : RiscvStaticInst(mnem, _machInst, __opClass), imm(0)
80        {}
81
82        virtual std::string
83        generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
84    };
85
86    /**
87     * Base class for operations with branching
88     */
89    class BranchOp : public ImmOp
90    {
91      protected:
92        /// Constructor
93        BranchOp(const char *mnem, MachInst _machInst, OpClass __opClass)
94            : ImmOp(mnem, _machInst, __opClass)
95        {}
96
97        using StaticInst::branchTarget;
98
99        virtual RiscvISA::PCState
100        branchTarget(ThreadContext *tc) const
101        {
102            return StaticInst::branchTarget(tc);
103        }
104
105        virtual RiscvISA::PCState
106        branchTarget(const RiscvISA::PCState &branchPC) const
107        {
108            return StaticInst::branchTarget(branchPC);
109        }
110
111        virtual std::string
112        generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
113    };
114
115    /**
116     * Base class for system operations
117     */
118    class SystemOp : public RiscvStaticInst
119    {
120      public:
121        /// Constructor
122        SystemOp(const char *mnem, MachInst _machInst, OpClass __opClass)
123            : RiscvStaticInst(mnem, _machInst, __opClass)
124        {}
125
126        std::string
127        generateDisassembly(Addr pc, const SymbolTable *symtab) const
128        {
129            return mnemonic;
130        }
131    };
132
133    /**
134     * Base class for CSR operations
135     */
136    class CSROp : public RiscvStaticInst
137    {
138      protected:
139        uint64_t csr;
140        uint64_t uimm;
141
142      public:
143        /// Constructor
144        CSROp(const char *mnem, MachInst _machInst, OpClass __opClass)
145            : RiscvStaticInst(mnem, _machInst, __opClass),
146              csr(FUNCT12), uimm(CSRIMM)
147        {}
148
149        std::string
150        generateDisassembly(Addr pc, const SymbolTable *symtab) const;
151    };
152}};
153
154//Outputs to decoder.cc
155output decoder {{
156    std::string
157    RegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
158    {
159        std::stringstream ss;
160        ss << mnemonic << ' ' << registerName(_destRegIdx[0]) << ", " <<
161            registerName(_srcRegIdx[0]) << ", " <<
162            registerName(_srcRegIdx[1]);
163        return ss.str();
164    }
165
166    std::string
167    CSROp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
168    {
169        std::stringstream ss;
170        ss << mnemonic << ' ' << registerName(_destRegIdx[0]) << ", ";
171        if (_numSrcRegs > 0)
172            ss << registerName(_srcRegIdx[0]) << ", ";
173        ss << MiscRegNames.at(csr);
174        return ss.str();
175    }
176}};
177
178def template ImmDeclare {{
179    //
180    // Static instruction class for "%(mnemonic)s".
181    //
182    class %(class_name)s : public %(base_class)s
183    {
184      public:
185        /// Constructor.
186        %(class_name)s(MachInst machInst);
187        %(BasicExecDeclare)s
188        std::string generateDisassembly(Addr pc,
189            const SymbolTable *symtab) const override;
190    };
191}};
192
193def template ImmConstructor {{
194    %(class_name)s::%(class_name)s(MachInst machInst)
195        : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
196    {
197        %(constructor)s;
198        %(imm_code)s;
199    }
200}};
201
202def template ImmExecute {{
203    Fault
204    %(class_name)s::execute(
205        ExecContext *xc, Trace::InstRecord *traceData) const
206    {
207        Fault fault = NoFault;
208
209        %(op_decl)s;
210        %(op_rd)s;
211        if (fault == NoFault) {
212            %(code)s;
213            if (fault == NoFault) {
214                %(op_wb)s;
215            }
216        }
217        return fault;
218    }
219
220    std::string
221    %(class_name)s::generateDisassembly(Addr pc,
222            const SymbolTable *symtab) const
223    {
224        std::vector<RegId> indices = {%(regs)s};
225        std::stringstream ss;
226        ss << mnemonic << ' ';
227        for (const RegId& idx: indices)
228            ss << registerName(idx) << ", ";
229        ss << imm;
230        return ss.str();
231    }
232}};
233
234def template BranchDeclare {{
235    //
236    // Static instruction class for "%(mnemonic)s".
237    //
238    class %(class_name)s : public %(base_class)s
239    {
240      public:
241        /// Constructor.
242        %(class_name)s(MachInst machInst);
243        %(BasicExecDeclare)s
244
245        std::string
246        generateDisassembly(Addr pc, const SymbolTable *symtab) const override;
247
248        RiscvISA::PCState
249        branchTarget(const RiscvISA::PCState &branchPC) const override;
250
251        using StaticInst::branchTarget;
252    };
253}};
254
255def template BranchExecute {{
256    Fault
257    %(class_name)s::execute(ExecContext *xc,
258        Trace::InstRecord *traceData) const
259    {
260        Fault fault = NoFault;
261
262        %(op_decl)s;
263        %(op_rd)s;
264        if (fault == NoFault) {
265            %(code)s;
266            if (fault == NoFault) {
267                %(op_wb)s;
268            }
269        }
270        return fault;
271    }
272
273    RiscvISA::PCState
274    %(class_name)s::branchTarget(const RiscvISA::PCState &branchPC) const
275    {
276        return branchPC.pc() + imm;
277    }
278
279    std::string
280    %(class_name)s::generateDisassembly(Addr pc,
281            const SymbolTable *symtab) const
282    {
283        std::vector<RegId> indices = {%(regs)s};
284        std::stringstream ss;
285        ss << mnemonic << ' ';
286        for (const RegId& idx: indices)
287            ss << registerName(idx) << ", ";
288        ss << imm;
289        return ss.str();
290    }
291}};
292
293def template JumpDeclare {{
294    //
295    // Static instruction class for "%(mnemonic)s".
296    //
297    class %(class_name)s : public %(base_class)s
298    {
299      public:
300        /// Constructor.
301        %(class_name)s(MachInst machInst);
302        %(BasicExecDeclare)s
303
304        std::string
305        generateDisassembly(Addr pc, const SymbolTable *symtab) const override;
306
307        RiscvISA::PCState
308        branchTarget(ThreadContext *tc) const override;
309
310        using StaticInst::branchTarget;
311    };
312}};
313
314def template JumpExecute {{
315    Fault
316    %(class_name)s::execute(
317        ExecContext *xc, Trace::InstRecord *traceData) const
318    {
319        Fault fault = NoFault;
320
321        %(op_decl)s;
322        %(op_rd)s;
323        if (fault == NoFault) {
324            %(code)s;
325            if (fault == NoFault) {
326                %(op_wb)s;
327            }
328        }
329        return fault;
330    }
331
332    RiscvISA::PCState
333    %(class_name)s::branchTarget(ThreadContext *tc) const
334    {
335        PCState pc = tc->pcState();
336        pc.set((tc->readIntReg(_srcRegIdx[0].index()) + imm)&~0x1);
337        return pc;
338    }
339
340    std::string
341    %(class_name)s::generateDisassembly(Addr pc,
342            const SymbolTable *symtab) const
343    {
344        std::vector<RegId> indices = {%(regs)s};
345        std::stringstream ss;
346        ss << mnemonic << ' ';
347        for (const RegId& idx: indices)
348            ss << registerName(idx) << ", ";
349        ss << imm;
350        return ss.str();
351    }
352}};
353
354def format ROp(code, *opt_flags) {{
355    iop = InstObjParams(name, Name, 'RegOp', code, opt_flags)
356    header_output = BasicDeclare.subst(iop)
357    decoder_output = BasicConstructor.subst(iop)
358    decode_block = BasicDecode.subst(iop)
359    exec_output = BasicExecute.subst(iop)
360}};
361
362def format IOp(code, *opt_flags) {{
363    imm_code = 'imm = IMM12; if (IMMSIGN > 0) imm |= ~((uint64_t)0x7FF);'
364    regs = ['_destRegIdx[0]','_srcRegIdx[0]']
365    iop = InstObjParams(name, Name, 'ImmOp',
366        {'code': code, 'imm_code': imm_code,
367         'regs': ','.join(regs)}, opt_flags)
368    header_output = ImmDeclare.subst(iop)
369    decoder_output = ImmConstructor.subst(iop)
370    decode_block = BasicDecode.subst(iop)
371    exec_output = ImmExecute.subst(iop)
372}};
373
374def format BOp(code, *opt_flags) {{
375    imm_code = """
376                imm |= BIMM12BIT11 << 11;
377                imm |= BIMM12BITS4TO1 << 1;
378                imm |= BIMM12BITS10TO5 << 5;
379                if (IMMSIGN > 0)
380                    imm |= ~((uint64_t)0xFFF);
381               """
382    regs = ['_srcRegIdx[0]','_srcRegIdx[1]']
383    iop = InstObjParams(name, Name, 'BranchOp',
384        {'code': code, 'imm_code': imm_code,
385         'regs': ','.join(regs)}, opt_flags)
386    header_output = BranchDeclare.subst(iop)
387    decoder_output = ImmConstructor.subst(iop)
388    decode_block = BasicDecode.subst(iop)
389    exec_output = BranchExecute.subst(iop)
390}};
391
392def format Jump(code, *opt_flags) {{
393    imm_code = 'imm = IMM12; if (IMMSIGN > 0) imm |= ~((uint64_t)0x7FF);'
394    regs = ['_destRegIdx[0]','_srcRegIdx[0]']
395    iop = InstObjParams(name, Name, 'BranchOp',
396        {'code': code, 'imm_code': imm_code,
397         'regs': ','.join(regs)}, opt_flags)
398    header_output = JumpDeclare.subst(iop)
399    decoder_output = ImmConstructor.subst(iop)
400    decode_block = BasicDecode.subst(iop)
401    exec_output = JumpExecute.subst(iop)
402}};
403
404def format UOp(code, *opt_flags) {{
405    imm_code = 'imm = (int32_t)(IMM20 << 12);'
406    regs = ['_destRegIdx[0]']
407    iop = InstObjParams(name, Name, 'ImmOp',
408        {'code': code, 'imm_code': imm_code,
409         'regs': ','.join(regs)}, opt_flags)
410    header_output = ImmDeclare.subst(iop)
411    decoder_output = ImmConstructor.subst(iop)
412    decode_block = BasicDecode.subst(iop)
413    exec_output = ImmExecute.subst(iop)
414}};
415
416def format JOp(code, *opt_flags) {{
417    imm_code = """
418                imm |= UJIMMBITS19TO12 << 12;
419                imm |= UJIMMBIT11 << 11;
420                imm |= UJIMMBITS10TO1 << 1;
421                if (IMMSIGN > 0)
422                    imm |= ~((uint64_t)0xFFFFF);
423               """
424    pc = 'pc.set(pc.pc() + imm);'
425    regs = ['_destRegIdx[0]']
426    iop = InstObjParams(name, Name, 'BranchOp',
427        {'code': code, 'imm_code': imm_code,
428         'regs': ','.join(regs)}, opt_flags)
429    header_output = BranchDeclare.subst(iop)
430    decoder_output = ImmConstructor.subst(iop)
431    decode_block = BasicDecode.subst(iop)
432    exec_output = BranchExecute.subst(iop)
433}};
434
435def format SystemOp(code, *opt_flags) {{
436    iop = InstObjParams(name, Name, 'SystemOp', code, opt_flags)
437    header_output = BasicDeclare.subst(iop)
438    decoder_output = BasicConstructor.subst(iop)
439    decode_block = BasicDecode.subst(iop)
440    exec_output = BasicExecute.subst(iop)
441}};
442
443def format CSROp(code, *opt_flags) {{
444    iop = InstObjParams(name, Name, 'CSROp', code, opt_flags)
445    header_output = BasicDeclare.subst(iop)
446    decoder_output = BasicConstructor.subst(iop)
447    decode_block = BasicDecode.subst(iop)
448    exec_output = BasicExecute.subst(iop)
449}};
450