1// Copyright (c) 2006-2007 The Regents of The University of Michigan
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met: redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer;
8// redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution;
11// neither the name of the copyright holders nor the names of its
12// contributors may be used to endorse or promote products derived from
13// this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26//
27// Authors: Ali Saidi
28//          Gabe Black
29//          Steve Reinhardt
30
31////////////////////////////////////////////////////////////////////
32//
33// Privilege mode instructions
34//
35
36def template ControlRegConstructor {{
37%(class_name)s::%(class_name)s(ExtMachInst machInst) :
38        %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, "%(reg_name)s")
39{
40    %(constructor)s;
41}
42}};
43
44def template PrivExecute {{
45Fault
46%(class_name)s::execute(ExecContext *xc, Trace::InstRecord *traceData) const
47{
48    %(op_decl)s;
49    %(op_rd)s;
50
51    // If the processor isn't in privileged mode, fault out right away
52    if (%(check)s)
53        return std::make_shared<PrivilegedAction>();
54
55    %(tl_check)s
56
57    Fault fault = NoFault;
58    %(code)s;
59    %(op_wb)s;
60    return fault;
61}
62}};
63
64let {{
65    tl_check_code = '''
66    if (Tl == 0)
67        return std::make_shared<IllegalInstruction>();
68'''
69
70    def doPrivFormat(code, check_code, name, Name, opt_flags, check_tl=False):
71        (uses_imm, code, imm_code, r_string, i_string) = splitOutImm(code)
72        tl_check = tl_check_code if check_tl else ''
73        # If these are rd, rdpr, rdhpr, wr, wrpr, or wrhpr instructions,
74        # cut any other info out of the mnemonic. Also pick a different
75        # base class.
76        reg_base = 'Priv'
77        reg_name = ''
78        for mnem in ["rdhpr", "rdpr", "rd"]:
79            if name.startswith(mnem):
80                reg_name = name[len(mnem):]
81                name = mnem
82                reg_base = 'RdPriv'
83                break
84        for mnem in ["wrhpr", "wrpr", "wr"]:
85            if name.startswith(mnem):
86                reg_name = name[len(mnem):]
87                name = mnem
88                reg_base = 'WrPriv'
89                break
90        iop = InstObjParams(name, Name, reg_base,
91                {"code": code, "check": check_code,
92                 "tl_check": tl_check, "reg_name": reg_name},
93                opt_flags)
94        header_output = BasicDeclare.subst(iop)
95        if reg_name == '':
96            decoder_output = BasicConstructor.subst(iop)
97        else:
98            decoder_output = ControlRegConstructor.subst(iop)
99        exec_output = PrivExecute.subst(iop)
100        if uses_imm:
101            imm_iop = InstObjParams(name, Name + 'Imm', reg_base + 'Imm',
102                    {"code": imm_code, "check": check_code,
103                     "tl_check": tl_check, "reg_name": reg_name},
104                    opt_flags)
105            header_output += BasicDeclare.subst(imm_iop)
106            if reg_name == '':
107                decoder_output += BasicConstructor.subst(imm_iop)
108            else:
109                decoder_output += ControlRegConstructor.subst(imm_iop)
110            exec_output += PrivExecute.subst(imm_iop)
111            decode_block = ROrImmDecode.subst(iop)
112        else:
113            decode_block = BasicDecode.subst(iop)
114        return (header_output, decoder_output, exec_output, decode_block)
115}};
116
117def format Priv(code, extraCond=true, check_tl=false, *opt_flags) {{
118    check_code = "(%s) && !(Pstate.priv || Hpstate.hpriv)" % extraCond
119    (header_output, decoder_output, exec_output, decode_block) = \
120            doPrivFormat(code, check_code, name, Name, opt_flags,
121                         check_tl=(check_tl != 'false'))
122}};
123
124def format NoPriv(code, *opt_flags) {{
125    # Instructions which use this format don't really check for any
126    # particular mode, but the disassembly is performed using the control
127    # register's actual name
128    check_code = "false"
129    (header_output, decoder_output, exec_output, decode_block) = \
130            doPrivFormat(code, check_code, name, Name, opt_flags)
131}};
132
133def format HPriv(code, check_tl=false, *opt_flags) {{
134    check_code = "!Hpstate.hpriv"
135    (header_output, decoder_output, exec_output, decode_block) = \
136            doPrivFormat(code, check_code, name, Name, opt_flags,
137                         check_tl=(check_tl != 'false'))
138}};
139
140