blob: 1c8ce63dd43ff419b8e9d94cc0f36573b0cc220d [file] [log] [blame]
// Copyright (c) 2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder. You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// 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.
def template BrDeclare {{
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
%(class_name)s(ExtMachInst mach_inst, const char *inst_mnem,
uint64_t set_flags, uint16_t _target, uint8_t _cc) :
%(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
%(op_class)s, { _target }, _cc)
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
std::unique_ptr<PCStateBase>
branchTarget(const PCStateBase &branch_pc) const override
{
PCStateBase *pcs = branch_pc.clone();
DPRINTF(X86, "Br branchTarget PC info: %s, Target: %d\n",
*pcs, (int16_t)target);
auto &xpc = pcs->as<PCState>();
xpc.nupc(target);
xpc.uAdvance();
return std::unique_ptr<PCStateBase>{pcs};
}
/// Explicitly import the otherwise hidden branchTarget
using StaticInst::branchTarget;
};
}};
def template EretDeclare {{
class %(class_name)s : public %(base_class)s
{
private:
%(reg_idx_arr_decl)s;
public:
%(class_name)s(ExtMachInst mach_inst, const char *inst_mnem,
uint64_t set_flags, uint8_t _cc) :
%(base_class)s(mach_inst, "%(mnemonic)s", inst_mnem, set_flags,
%(op_class)s, {}, _cc)
{
%(set_reg_idx_arr)s;
%(constructor)s;
}
Fault execute(ExecContext *, Trace::InstRecord *) const override;
};
}};
def template SeqOpExecute {{
Fault
%(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
%(op_decl)s;
%(op_rd)s;
if (%(cond_test)s) {
%(code)s;
} else {
%(else_code)s;
}
%(op_wb)s;
return NoFault;
}
}};
let {{
class Br(X86Microop):
def __init__(self, target, flags=None):
self.className = "Br"
self.target = target
if flags:
if not isinstance(flags, (list, tuple)):
raise Exception("flags must be a list or tuple of flags")
self.cond = " | ".join(flags)
self.className += "Flags"
else:
self.cond = "0"
def getAllocator(self, microFlags):
if "IsLastMicroop" in microFlags:
microFlags.remove("IsLastMicroop")
if not "IsDelayedCommit" in microFlags:
microFlags.append("IsDelayedCommit")
return '''new %(class_name)s(machInst, macrocodeBlock,
%(flags)s, %(target)s, %(cc)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags),
"target" : self.target,
"cc" : self.cond}
microopClasses["br"] = Br
class Eret(X86Microop):
def __init__(self, flags=None):
self.className = "Eret"
if flags:
if not isinstance(flags, (list, tuple)):
raise Exception("flags must be a list or tuple of flags")
self.cond = " | ".join(flags)
self.className += "Flags"
else:
self.cond = "X86ISA::condition_tests::True"
def getAllocator(self, microFlags):
if not "IsLastMicroop" in microFlags:
microFlags.append("IsLastMicroop")
if "IsDelayedCommit" in microFlags:
microFlags.remove("IsDelayedCommit")
return '''new %(class_name)s(machInst, macrocodeBlock,
%(flags)s, %(cc)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags),
"cc" : self.cond}
microopClasses["eret"] = Eret
cond_code = "checkCondition(ccFlagBits | cfofBits | dfBit |" \
"ecfBit | ezfBit, cc)"
for suffix, cond, flags in \
("Flags", cond_code, ["IsDirectControl", "IsCondControl"]), \
("", "true", []):
iop = InstObjParams("br", "Br" + suffix,
"X86ISA::InstOperands<X86ISA::MicroCondBase, X86ISA::UpcOp>",
{"code": "nuIP = target;", "else_code": "nuIP = nuIP;",
"cond_test": cond},
flags)
exec_output += SeqOpExecute.subst(iop)
header_output += BrDeclare.subst(iop)
iop = InstObjParams("eret", "Eret" + suffix,
"X86ISA::InstOperands<X86ISA::MicroCondBase>",
{"code": "", "else_code": "", "cond_test": cond}, flags)
exec_output += SeqOpExecute.subst(iop)
header_output += EretDeclare.subst(iop)
}};