macroop.isa revision 5046:da031ef02439
11761SN/A// -*- mode:c++ -*- 22SN/A 32SN/A// Copyright (c) 2007 The Hewlett-Packard Development Company 42SN/A// All rights reserved. 52SN/A// 62SN/A// Redistribution and use of this software in source and binary forms, 72SN/A// with or without modification, are permitted provided that the 82SN/A// following conditions are met: 92SN/A// 102SN/A// The software must be used only for Non-Commercial Use which means any 112SN/A// use which is NOT directed to receiving any direct monetary 122SN/A// compensation for, or commercial advantage from such use. Illustrative 132SN/A// examples of non-commercial use are academic research, personal study, 142SN/A// teaching, education and corporate research & development. 152SN/A// Illustrative examples of commercial use are distributing products for 162SN/A// commercial advantage and providing services using the software for 172SN/A// commercial advantage. 182SN/A// 192SN/A// If you wish to use this software or functionality therein that may be 202SN/A// covered by patents for commercial use, please contact: 212SN/A// Director of Intellectual Property Licensing 222SN/A// Office of Strategy and Technology 232SN/A// Hewlett-Packard Company 242SN/A// 1501 Page Mill Road 252SN/A// Palo Alto, California 94304 262665Ssaidi@eecs.umich.edu// 272665Ssaidi@eecs.umich.edu// Redistributions of source code must retain the above copyright notice, 282SN/A// this list of conditions and the following disclaimer. Redistributions 292SN/A// in binary form must reproduce the above copyright notice, this list of 302SN/A// conditions and the following disclaimer in the documentation and/or 312SN/A// other materials provided with the distribution. Neither the name of 322SN/A// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 33705SN/A// contributors may be used to endorse or promote products derived from 342SN/A// this software without specific prior written permission. No right of 352SN/A// sublicense is granted herewith. Derivatives of the software and 362SN/A// output created using the software may be prepared, but only for 376661Snate@binkert.org// Non-Commercial Uses. Derivatives of the software may be shared with 382SN/A// others provided: (i) the others agree to abide by the list of 396661Snate@binkert.org// conditions herein which includes the Non-Commercial Use restrictions; 406661Snate@binkert.org// and (ii) such Derivatives of the software include the above copyright 416661Snate@binkert.org// notice to acknowledge the contribution from this software where 426661Snate@binkert.org// applicable, this list of conditions and the disclaimer below. 432SN/A// 446661Snate@binkert.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 456661Snate@binkert.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 466661Snate@binkert.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 476661Snate@binkert.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 486661Snate@binkert.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 496661Snate@binkert.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 506661Snate@binkert.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 516661Snate@binkert.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 526661Snate@binkert.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 536661Snate@binkert.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 546661Snate@binkert.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 556661Snate@binkert.org// 566661Snate@binkert.org// Authors: Gabe Black 576661Snate@binkert.org 586661Snate@binkert.org////////////////////////////////////////////////////////////////////////////// 596661Snate@binkert.org// 606661Snate@binkert.org// Architecture independent 616661Snate@binkert.org// 626661Snate@binkert.org 636661Snate@binkert.org// Execute method for macroops. 646661Snate@binkert.orgdef template MacroExecPanic {{ 656661Snate@binkert.org Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const 666661Snate@binkert.org { 676661Snate@binkert.org panic("Tried to execute macroop directly!"); 686661Snate@binkert.org return NoFault; 696661Snate@binkert.org } 706661Snate@binkert.org}}; 716661Snate@binkert.org 726661Snate@binkert.orgoutput header {{ 736661Snate@binkert.org 746661Snate@binkert.org // Base class for combinationally generated macroops 756661Snate@binkert.org class Macroop : public StaticInst 766661Snate@binkert.org { 776661Snate@binkert.org protected: 786661Snate@binkert.org const uint32_t numMicroops; 796661Snate@binkert.org 806661Snate@binkert.org //Constructor. 816661Snate@binkert.org Macroop(const char *mnem, ExtMachInst _machInst, 826661Snate@binkert.org uint32_t _numMicroops) 836661Snate@binkert.org : StaticInst(mnem, _machInst, No_OpClass), 846661Snate@binkert.org numMicroops(_numMicroops) 856661Snate@binkert.org { 866661Snate@binkert.org assert(numMicroops); 876661Snate@binkert.org microops = new StaticInstPtr[numMicroops]; 886661Snate@binkert.org flags[IsMacroop] = true; 896661Snate@binkert.org } 906661Snate@binkert.org 916661Snate@binkert.org ~Macroop() 926661Snate@binkert.org { 936661Snate@binkert.org delete [] microops; 946661Snate@binkert.org } 956661Snate@binkert.org 966661Snate@binkert.org StaticInstPtr * microops; 976661Snate@binkert.org 986661Snate@binkert.org StaticInstPtr fetchMicroop(MicroPC microPC) 996661Snate@binkert.org { 1002SN/A assert(microPC < numMicroops); 1012SN/A return microops[microPC]; 1026661Snate@binkert.org } 1036661Snate@binkert.org 1046661Snate@binkert.org std::string generateDisassembly(Addr pc, 1056661Snate@binkert.org const SymbolTable *symtab) const 1066661Snate@binkert.org { 1076661Snate@binkert.org return mnemonic; 1086661Snate@binkert.org } 1096661Snate@binkert.org 1106661Snate@binkert.org %(MacroExecPanic)s 1116661Snate@binkert.org }; 1126661Snate@binkert.org}}; 1136661Snate@binkert.org 1146661Snate@binkert.org////////////////////////////////////////////////////////////////////////////// 1156661Snate@binkert.org// 1166661Snate@binkert.org// X86 specific 1176661Snate@binkert.org// 1182SN/A////////////////////////////////////////////////////////////////////////////// 1196661Snate@binkert.org 1206661Snate@binkert.org// Basic instruction class declaration template. 1216661Snate@binkert.orgdef template MacroDeclare {{ 1226661Snate@binkert.org namespace X86Macroop 1232SN/A { 1246661Snate@binkert.org /** 1256661Snate@binkert.org * Static instruction class for "%(mnemonic)s". 1266661Snate@binkert.org */ 1276661Snate@binkert.org class %(class_name)s : public %(base_class)s 1282SN/A { 1296661Snate@binkert.org private: 1306661Snate@binkert.org %(declareLabels)s 1316866Snate@binkert.org public: 1326661Snate@binkert.org // Constructor. 1336661Snate@binkert.org %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env); 1346661Snate@binkert.org }; 1356661Snate@binkert.org }; 1366661Snate@binkert.org}}; 1376661Snate@binkert.org 1382SN/A// Basic instruction class constructor template. 1396661Snate@binkert.orgdef template MacroConstructor {{ 1406661Snate@binkert.org inline X86Macroop::%(class_name)s::%(class_name)s( 1416661Snate@binkert.org ExtMachInst machInst, EmulEnv env) 1426661Snate@binkert.org : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s) 1436661Snate@binkert.org { 1446661Snate@binkert.org %(adjust_env)s; 1456661Snate@binkert.org %(do_modrm)s; 1466661Snate@binkert.org %(constructor)s; 1472SN/A //alloc_microops is the code that sets up the microops 1482023SN/A //array in the parent class. 1496661Snate@binkert.org %(alloc_microops)s; 1506661Snate@binkert.org } 1516661Snate@binkert.org}}; 1526661Snate@binkert.org 1536661Snate@binkert.orglet {{ 1546661Snate@binkert.org from micro_asm import Combinational_Macroop, Rom_Macroop 1556661Snate@binkert.org class X86Macroop(Combinational_Macroop): 1566661Snate@binkert.org def add_microop(self, mnemonic, microop): 1572023SN/A microop.mnemonic = mnemonic 1586661Snate@binkert.org microop.micropc = len(self.microops) 1596661Snate@binkert.org self.microops.append(microop) 1606661Snate@binkert.org def setAdjustEnv(self, val): 1616661Snate@binkert.org self.adjust_env = val 1622SN/A def __init__(self, name): 1636661Snate@binkert.org super(X86Macroop, self).__init__(name) 1646661Snate@binkert.org self.directives = { 1656661Snate@binkert.org "adjust_env" : self.setAdjustEnv 1666661Snate@binkert.org } 1672SN/A self.declared = False 1686661Snate@binkert.org self.adjust_env = "" 1696661Snate@binkert.org self.doModRM = "" 1706661Snate@binkert.org def getAllocator(self, env): 1712SN/A return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator()) 1726661Snate@binkert.org def getDeclaration(self): 1736661Snate@binkert.org #FIXME This first parameter should be the mnemonic. I need to 1746661Snate@binkert.org #write some code which pulls that out 1756661Snate@binkert.org declareLabels = "" 1762SN/A for (label, microop) in self.labels.items(): 1776661Snate@binkert.org declareLabels += "const static uint64_t label_%s = %d;\n" \ 1786661Snate@binkert.org % (label, microop.micropc) 1796661Snate@binkert.org iop = InstObjParams(self.name, self.name, "Macroop", 1806661Snate@binkert.org {"code" : "", 1812SN/A "declareLabels" : declareLabels 1826661Snate@binkert.org }) 1836661Snate@binkert.org return MacroDeclare.subst(iop); 1846661Snate@binkert.org def getDefinition(self): 1852SN/A #FIXME This first parameter should be the mnemonic. I need to 1866661Snate@binkert.org #write some code which pulls that out 1876661Snate@binkert.org numMicroops = len(self.microops) 1882SN/A allocMicroops = '' 1896661Snate@binkert.org micropc = 0 1906661Snate@binkert.org for op in self.microops: 1916661Snate@binkert.org allocMicroops += \ 1926661Snate@binkert.org "microops[%d] = %s;\n" % \ 1932SN/A (micropc, op.getAllocator(True, False, 1946661Snate@binkert.org micropc == 0, 1956661Snate@binkert.org micropc == numMicroops - 1)) 1966661Snate@binkert.org micropc += 1 1976661Snate@binkert.org iop = InstObjParams(self.name, self.name, "Macroop", 1986661Snate@binkert.org {"code" : "", "num_microops" : numMicroops, 1996661Snate@binkert.org "alloc_microops" : allocMicroops, 2006661Snate@binkert.org "adjust_env" : self.adjust_env, 2016661Snate@binkert.org "do_modrm" : self.doModRM}) 2026661Snate@binkert.org return MacroConstructor.subst(iop); 2036661Snate@binkert.org}}; 2046661Snate@binkert.org 2056661Snate@binkert.orglet {{ 2066661Snate@binkert.org class EmulEnv(object): 2076661Snate@binkert.org def __init__(self): 2086661Snate@binkert.org self.reg = "0" 2092SN/A self.regUsed = False 2106661Snate@binkert.org self.regm = "0" 2116661Snate@binkert.org self.regmUsed = False 2126661Snate@binkert.org self.seg = "SEGMENT_REG_DS" 2136661Snate@binkert.org self.size = None 2146661Snate@binkert.org self.addressSize = "ADDRSIZE" 2156661Snate@binkert.org self.dataSize = "OPSIZE" 2166661Snate@binkert.org self.stackSize = "STACKSIZE" 2176661Snate@binkert.org self.doModRM = False 2186661Snate@binkert.org 2196661Snate@binkert.org def getAllocator(self): 2206661Snate@binkert.org if self.size == 'b': 2216661Snate@binkert.org self.dataSize = 1 2226661Snate@binkert.org elif self.size == 'd': 2236661Snate@binkert.org self.dataSize = 4 2242107SN/A #This is for "double plus" which is normally a double word unless 2252227SN/A #the REX W bit is set, in which case it's a quad word. It's used 2262SN/A #for some SSE instructions. 2272SN/A elif self.size == 'dp': 228715SN/A self.dataSize = "(REX_W ? 8 : 4)" 2296661Snate@binkert.org elif self.size == 'q': 2306661Snate@binkert.org self.dataSize = 8 2316661Snate@binkert.org elif self.size == 'v': 2326661Snate@binkert.org self.dataSize = "OPSIZE" 2336661Snate@binkert.org elif self.size == 'w': 2342SN/A self.dataSize = 2 2356661Snate@binkert.org elif self.size == 'z': 2366661Snate@binkert.org self.dataSize = "((OPSIZE == 8) ? 4 : OPSIZE)" 2376661Snate@binkert.org elif self.size: 2386661Snate@binkert.org raise Exception, "Unrecognized size type %s!" % self.size 2392SN/A return '''EmulEnv(%(reg)s, 2406661Snate@binkert.org %(regm)s, 2416661Snate@binkert.org %(dataSize)s, 2426661Snate@binkert.org %(addressSize)s, 2436661Snate@binkert.org %(stackSize)s)''' % \ 2446661Snate@binkert.org self.__dict__ 2452SN/A 2466661Snate@binkert.org def addReg(self, reg): 2476661Snate@binkert.org if not self.regUsed: 2486661Snate@binkert.org self.reg = reg 2492SN/A self.regUsed = True 2506661Snate@binkert.org elif not self.regmUsed: 2516661Snate@binkert.org self.regm = reg 2526661Snate@binkert.org self.regmUsed = True 2532SN/A else: 2546661Snate@binkert.org raise Exception, "EmulEnv is out of register specialization spots." 2556661Snate@binkert.org def setSize(self, size): 2566661Snate@binkert.org if not self.size: 2572SN/A self.size = size 2586661Snate@binkert.org else: 2596661Snate@binkert.org if self.size != size: 2606661Snate@binkert.org raise Exception, "Conflicting register sizes %s and %s!" %\ 2616661Snate@binkert.org (self.size, size) 2626661Snate@binkert.org}}; 2636661Snate@binkert.org 2646661Snate@binkert.orglet {{ 2656661Snate@binkert.org doModRMString = "env.doModRM(machInst);\n" 2666661Snate@binkert.org def genMacroop(Name, env): 2676661Snate@binkert.org blocks = OutputBlocks() 2686661Snate@binkert.org if not macroopDict.has_key(Name): 2696661Snate@binkert.org raise Exception, "Unrecognized instruction: %s" % Name 2706661Snate@binkert.org macroop = macroopDict[Name] 2712SN/A if not macroop.declared: 2726661Snate@binkert.org if env.doModRM: 2736661Snate@binkert.org macroop.doModRM = doModRMString 2742SN/A blocks.header_output = macroop.getDeclaration() 2756661Snate@binkert.org blocks.decoder_output = macroop.getDefinition() 2766661Snate@binkert.org macroop.declared = True 2776661Snate@binkert.org blocks.decode_block = "return %s;\n" % macroop.getAllocator(env) 2786661Snate@binkert.org return blocks 2796661Snate@binkert.org}}; 2806661Snate@binkert.org