// 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. // // Authors: Ali Saidi // Gabe Black // Steve Reinhardt //////////////////////////////////////////////////////////////////// // // 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") { %(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(); %(tl_check)s Fault fault = NoFault; %(code)s; %(op_wb)s; return fault; } }}; let {{ tl_check_code = ''' if (Tl == 0) return std::make_shared(); ''' def doPrivFormat(code, check_code, name, Name, opt_flags, check_tl=False): (uses_imm, code, imm_code, r_string, i_string) = 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 uses_imm: 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')) }};