X86: Set up a media microop framework and create mov2int and mov2fp microops.
This commit is contained in:
parent
cec4e3b39e
commit
2f1001e95c
3 changed files with 315 additions and 0 deletions
|
@ -100,6 +100,7 @@ output header {{
|
||||||
#include "arch/x86/insts/macroop.hh"
|
#include "arch/x86/insts/macroop.hh"
|
||||||
#include "arch/x86/insts/microfpop.hh"
|
#include "arch/x86/insts/microfpop.hh"
|
||||||
#include "arch/x86/insts/microldstop.hh"
|
#include "arch/x86/insts/microldstop.hh"
|
||||||
|
#include "arch/x86/insts/micromediaop.hh"
|
||||||
#include "arch/x86/insts/microregop.hh"
|
#include "arch/x86/insts/microregop.hh"
|
||||||
#include "arch/x86/insts/static_inst.hh"
|
#include "arch/x86/insts/static_inst.hh"
|
||||||
#include "arch/x86/isa_traits.hh"
|
#include "arch/x86/isa_traits.hh"
|
||||||
|
|
311
src/arch/x86/isa/microops/mediaop.isa
Normal file
311
src/arch/x86/isa/microops/mediaop.isa
Normal file
|
@ -0,0 +1,311 @@
|
||||||
|
/// Copyright (c) 2009 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: Gabe Black
|
||||||
|
|
||||||
|
def template MediaOpExecute {{
|
||||||
|
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
||||||
|
Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
Fault fault = NoFault;
|
||||||
|
|
||||||
|
%(op_decl)s;
|
||||||
|
%(op_rd)s;
|
||||||
|
|
||||||
|
%(code)s;
|
||||||
|
|
||||||
|
//Write the resulting state to the execution context
|
||||||
|
if(fault == NoFault)
|
||||||
|
{
|
||||||
|
%(op_wb)s;
|
||||||
|
}
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
def template MediaOpRegDeclare {{
|
||||||
|
class %(class_name)s : public %(base_class)s
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void buildMe();
|
||||||
|
|
||||||
|
public:
|
||||||
|
%(class_name)s(ExtMachInst _machInst,
|
||||||
|
const char * instMnem,
|
||||||
|
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||||
|
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
|
||||||
|
uint8_t _srcSize, uint8_t _destSize, uint16_t _sel);
|
||||||
|
|
||||||
|
%(class_name)s(ExtMachInst _machInst,
|
||||||
|
const char * instMnem,
|
||||||
|
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
|
||||||
|
uint8_t _srcSize, uint8_t _destSize, uint16_t _sel);
|
||||||
|
|
||||||
|
%(BasicExecDeclare)s
|
||||||
|
};
|
||||||
|
}};
|
||||||
|
|
||||||
|
def template MediaOpImmDeclare {{
|
||||||
|
|
||||||
|
class %(class_name)s : public %(base_class)s
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void buildMe();
|
||||||
|
|
||||||
|
public:
|
||||||
|
%(class_name)s(ExtMachInst _machInst,
|
||||||
|
const char * instMnem,
|
||||||
|
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||||
|
InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest,
|
||||||
|
uint8_t _srcSize, uint8_t _destSize, uint16_t _sel);
|
||||||
|
|
||||||
|
%(class_name)s(ExtMachInst _machInst,
|
||||||
|
const char * instMnem,
|
||||||
|
InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest,
|
||||||
|
uint8_t _srcSize, uint8_t _destSize, uint16_t _sel);
|
||||||
|
|
||||||
|
%(BasicExecDeclare)s
|
||||||
|
};
|
||||||
|
}};
|
||||||
|
|
||||||
|
def template MediaOpRegConstructor {{
|
||||||
|
|
||||||
|
inline void %(class_name)s::buildMe()
|
||||||
|
{
|
||||||
|
%(constructor)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline %(class_name)s::%(class_name)s(
|
||||||
|
ExtMachInst machInst, const char * instMnem,
|
||||||
|
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
|
||||||
|
uint8_t _srcSize, uint8_t _destSize, uint16_t _sel) :
|
||||||
|
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||||
|
false, false, false, false,
|
||||||
|
_src1, _src2, _dest, _srcSize, _destSize, _sel,
|
||||||
|
%(op_class)s)
|
||||||
|
{
|
||||||
|
buildMe();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline %(class_name)s::%(class_name)s(
|
||||||
|
ExtMachInst machInst, const char * instMnem,
|
||||||
|
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||||
|
InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest,
|
||||||
|
uint8_t _srcSize, uint8_t _destSize, uint16_t _sel) :
|
||||||
|
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||||
|
isMicro, isDelayed, isFirst, isLast,
|
||||||
|
_src1, _src2, _dest, _srcSize, _destSize, _sel,
|
||||||
|
%(op_class)s)
|
||||||
|
{
|
||||||
|
buildMe();
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
def template MediaOpImmConstructor {{
|
||||||
|
|
||||||
|
inline void %(class_name)s::buildMe()
|
||||||
|
{
|
||||||
|
%(constructor)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline %(class_name)s::%(class_name)s(
|
||||||
|
ExtMachInst machInst, const char * instMnem,
|
||||||
|
InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest,
|
||||||
|
uint8_t _srcSize, uint8_t _destSize, uint16_t _sel) :
|
||||||
|
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||||
|
false, false, false, false,
|
||||||
|
_src1, _imm8, _dest, _srcSize, _destSize, _sel,
|
||||||
|
%(op_class)s)
|
||||||
|
{
|
||||||
|
buildMe();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline %(class_name)s::%(class_name)s(
|
||||||
|
ExtMachInst machInst, const char * instMnem,
|
||||||
|
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||||
|
InstRegIndex _src1, uint16_t _imm8, InstRegIndex _dest,
|
||||||
|
uint8_t _srcSize, uint8_t _destSize, uint16_t _sel) :
|
||||||
|
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||||
|
isMicro, isDelayed, isFirst, isLast,
|
||||||
|
_src1, _imm8, _dest, _srcSize, _destSize, _sel,
|
||||||
|
%(op_class)s)
|
||||||
|
{
|
||||||
|
buildMe();
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
let {{
|
||||||
|
# Make these empty strings so that concatenating onto
|
||||||
|
# them will always work.
|
||||||
|
header_output = ""
|
||||||
|
decoder_output = ""
|
||||||
|
exec_output = ""
|
||||||
|
|
||||||
|
immTemplates = (
|
||||||
|
MediaOpImmDeclare,
|
||||||
|
MediaOpImmConstructor,
|
||||||
|
MediaOpExecute)
|
||||||
|
|
||||||
|
regTemplates = (
|
||||||
|
MediaOpRegDeclare,
|
||||||
|
MediaOpRegConstructor,
|
||||||
|
MediaOpExecute)
|
||||||
|
|
||||||
|
class MediaOpMeta(type):
|
||||||
|
def buildCppClasses(self, name, Name, suffix, code):
|
||||||
|
|
||||||
|
# Globals to stick the output in
|
||||||
|
global header_output
|
||||||
|
global decoder_output
|
||||||
|
global exec_output
|
||||||
|
|
||||||
|
# If op2 is used anywhere, make register and immediate versions
|
||||||
|
# of this code.
|
||||||
|
matcher = re.compile("(?<!\\w)(?P<prefix>s?)op2(?P<typeQual>\\.\\w+)?")
|
||||||
|
match = matcher.search(code)
|
||||||
|
if match:
|
||||||
|
typeQual = ""
|
||||||
|
if match.group("typeQual"):
|
||||||
|
typeQual = match.group("typeQual")
|
||||||
|
src2_name = "%spsrc2%s" % (match.group("prefix"), typeQual)
|
||||||
|
self.buildCppClasses(name, Name, suffix,
|
||||||
|
matcher.sub(src2_name, code))
|
||||||
|
self.buildCppClasses(name + "i", Name, suffix + "Imm",
|
||||||
|
matcher.sub("imm8", code))
|
||||||
|
return
|
||||||
|
|
||||||
|
base = "X86ISA::MediaOp"
|
||||||
|
|
||||||
|
# If imm8 shows up in the code, use the immediate templates, if
|
||||||
|
# not, hopefully the register ones will be correct.
|
||||||
|
matcher = re.compile("(?<!\w)imm8(?!\w)")
|
||||||
|
if matcher.search(code):
|
||||||
|
base += "Imm"
|
||||||
|
templates = immTemplates
|
||||||
|
else:
|
||||||
|
base += "Reg"
|
||||||
|
templates = regTemplates
|
||||||
|
|
||||||
|
# Get everything ready for the substitution
|
||||||
|
iop = InstObjParams(name, Name + suffix, base, {"code" : code})
|
||||||
|
|
||||||
|
# Generate the actual code (finally!)
|
||||||
|
header_output += templates[0].subst(iop)
|
||||||
|
decoder_output += templates[1].subst(iop)
|
||||||
|
exec_output += templates[2].subst(iop)
|
||||||
|
|
||||||
|
|
||||||
|
def __new__(mcls, Name, bases, dict):
|
||||||
|
abstract = False
|
||||||
|
name = Name.lower()
|
||||||
|
if "abstract" in dict:
|
||||||
|
abstract = dict['abstract']
|
||||||
|
del dict['abstract']
|
||||||
|
|
||||||
|
cls = super(MediaOpMeta, mcls).__new__(mcls, Name, bases, dict)
|
||||||
|
if not abstract:
|
||||||
|
cls.className = Name
|
||||||
|
cls.base_mnemonic = name
|
||||||
|
code = cls.code
|
||||||
|
|
||||||
|
# Set up the C++ classes
|
||||||
|
mcls.buildCppClasses(cls, name, Name, "", code)
|
||||||
|
|
||||||
|
# Hook into the microassembler dict
|
||||||
|
global microopClasses
|
||||||
|
microopClasses[name] = cls
|
||||||
|
|
||||||
|
# If op2 is used anywhere, make register and immediate versions
|
||||||
|
# of this code.
|
||||||
|
matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
|
||||||
|
if matcher.search(code):
|
||||||
|
microopClasses[name + 'i'] = cls
|
||||||
|
return cls
|
||||||
|
|
||||||
|
|
||||||
|
class MediaOp(X86Microop):
|
||||||
|
__metaclass__ = MediaOpMeta
|
||||||
|
# This class itself doesn't act as a microop
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
def __init__(self, dest, src1, op2,
|
||||||
|
size = None, destSize = None, srcSize = None, sel = None):
|
||||||
|
self.dest = dest
|
||||||
|
self.src1 = src1
|
||||||
|
self.op2 = op2
|
||||||
|
if size is not None:
|
||||||
|
self.srcSize = size
|
||||||
|
self.destSize = size
|
||||||
|
if srcSize is not None:
|
||||||
|
self.srcSize = srcSize
|
||||||
|
if destSize is not None:
|
||||||
|
self.destSize = destSize
|
||||||
|
if self.srcSize is None:
|
||||||
|
raise Exception, "Source size not set."
|
||||||
|
if self.destSize is None:
|
||||||
|
raise Exception, "Dest size not set."
|
||||||
|
if sel is None:
|
||||||
|
self.sel = 0
|
||||||
|
else:
|
||||||
|
self.sel = sel
|
||||||
|
|
||||||
|
def getAllocator(self, *microFlags):
|
||||||
|
className = self.className
|
||||||
|
if self.mnemonic == self.base_mnemonic + 'i':
|
||||||
|
className += "Imm"
|
||||||
|
allocator = '''new %(class_name)s(machInst, macrocodeBlock
|
||||||
|
%(flags)s, %(src1)s, %(op2)s, %(dest)s,
|
||||||
|
%(srcSize)s, %(destSize)s, %(sel)s)''' % {
|
||||||
|
"class_name" : className,
|
||||||
|
"flags" : self.microFlagsText(microFlags),
|
||||||
|
"src1" : self.src1, "op2" : self.op2,
|
||||||
|
"dest" : self.dest,
|
||||||
|
"srcSize" : self.srcSize,
|
||||||
|
"destSize" : self.destSize,
|
||||||
|
"sel" : self.sel}
|
||||||
|
return allocator
|
||||||
|
|
||||||
|
class Mov2int(MediaOp):
|
||||||
|
def __init__(self, dest, src, \
|
||||||
|
size = None, destSize = None, srcSize = None, sel = None):
|
||||||
|
super(Mov2int, self).__init__(dest, src,\
|
||||||
|
"InstRegIndex(0)", size, destSize, srcSize, sel)
|
||||||
|
code = '''
|
||||||
|
uint64_t fpSrcReg1 = bits(FpSrcReg1.uqw, srcSize * 8 - 1, 0);
|
||||||
|
DestReg = merge(DestReg, fpSrcReg1, destSize);
|
||||||
|
'''
|
||||||
|
|
||||||
|
class Mov2fp(MediaOp):
|
||||||
|
def __init__(self, dest, src, \
|
||||||
|
size = None, destSize = None, srcSize = None, sel = None):
|
||||||
|
super(Mov2fp, self).__init__(dest, src,\
|
||||||
|
"InstRegIndex(0)", size, destSize, srcSize, sel)
|
||||||
|
code = '''
|
||||||
|
uint64_t srcReg1 = pick(SrcReg1, 0, srcSize);
|
||||||
|
FpDestReg.uqw =
|
||||||
|
insertBits(FpDestReg.uqw, destSize * 8 - 1, 0, srcReg1);
|
||||||
|
'''
|
||||||
|
}};
|
|
@ -68,6 +68,9 @@
|
||||||
//Load/store microop definitions
|
//Load/store microop definitions
|
||||||
##include "ldstop.isa"
|
##include "ldstop.isa"
|
||||||
|
|
||||||
|
//Media microop definitions
|
||||||
|
##include "mediaop.isa"
|
||||||
|
|
||||||
//Control flow microop definitions
|
//Control flow microop definitions
|
||||||
##include "seqop.isa"
|
##include "seqop.isa"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue