blob: a0c3a18d451bc9e93d7278094c2bd0c6de98275e [file] [log] [blame]
// Copyright (c) 2006-2007 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////
//
// Privilege mode instructions
//
def template ControlRegConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst) :
%(base_class)s("%(mnemonic)s", machInst, %(op_class)s, "%(reg_name)s")
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
}};
def template PrivExecute {{
Fault
%(class_name)s::execute(ExecContext *xc, Trace::InstRecord *traceData) const
{
%(op_decl)s;
%(op_rd)s;
// If the processor isn't in privileged mode, fault out right away
if (%(check)s)
return std::make_shared<PrivilegedAction>();
%(tl_check)s
Fault fault = NoFault;
%(code)s;
%(op_wb)s;
return fault;
}
}};
let {{
tl_check_code = '''
if (Tl == 0)
return std::make_shared<IllegalInstruction>();
'''
def doPrivFormat(code, check_code, name, Name, opt_flags, check_tl=False):
code, imm_code, _ = splitOutImm(code)
tl_check = tl_check_code if check_tl else ''
# If these are rd, rdpr, rdhpr, wr, wrpr, or wrhpr instructions,
# cut any other info out of the mnemonic. Also pick a different
# base class.
reg_base = 'Priv'
reg_name = ''
for mnem in ["rdhpr", "rdpr", "rd"]:
if name.startswith(mnem):
reg_name = name[len(mnem):]
name = mnem
reg_base = 'RdPriv'
break
for mnem in ["wrhpr", "wrpr", "wr"]:
if name.startswith(mnem):
reg_name = name[len(mnem):]
name = mnem
reg_base = 'WrPriv'
break
iop = InstObjParams(name, Name, reg_base,
{"code": code, "check": check_code,
"tl_check": tl_check, "reg_name": reg_name},
opt_flags)
header_output = BasicDeclare.subst(iop)
if reg_name == '':
decoder_output = BasicConstructor.subst(iop)
else:
decoder_output = ControlRegConstructor.subst(iop)
exec_output = PrivExecute.subst(iop)
if imm_code is not None:
imm_iop = InstObjParams(name, Name + 'Imm', reg_base + 'Imm',
{"code": imm_code, "check": check_code,
"tl_check": tl_check, "reg_name": reg_name},
opt_flags)
header_output += BasicDeclare.subst(imm_iop)
if reg_name == '':
decoder_output += BasicConstructor.subst(imm_iop)
else:
decoder_output += ControlRegConstructor.subst(imm_iop)
exec_output += PrivExecute.subst(imm_iop)
decode_block = ROrImmDecode.subst(iop)
else:
decode_block = BasicDecode.subst(iop)
return (header_output, decoder_output, exec_output, decode_block)
}};
def format Priv(code, extraCond=true, check_tl=false, *opt_flags) {{
check_code = "(%s) && !(Pstate.priv || Hpstate.hpriv)" % extraCond
(header_output, decoder_output, exec_output, decode_block) = \
doPrivFormat(code, check_code, name, Name, opt_flags,
check_tl=(check_tl != 'false'))
}};
def format NoPriv(code, *opt_flags) {{
# Instructions which use this format don't really check for any
# particular mode, but the disassembly is performed using the control
# register's actual name
check_code = "false"
(header_output, decoder_output, exec_output, decode_block) = \
doPrivFormat(code, check_code, name, Name, opt_flags)
}};
def format HPriv(code, check_tl=false, *opt_flags) {{
check_code = "!Hpstate.hpriv"
(header_output, decoder_output, exec_output, decode_block) = \
doPrivFormat(code, check_code, name, Name, opt_flags,
check_tl=(check_tl != 'false'))
}};