diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/alpha/tlb.cc | 4 | ||||
-rwxr-xr-x | src/arch/isa_parser.py | 7 | ||||
-rw-r--r-- | src/arch/micro_asm.py | 433 | ||||
-rwxr-xr-x | src/arch/micro_asm_test.py | 91 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/one_byte_opcodes.isa | 10 | ||||
-rw-r--r-- | src/arch/x86/predecoder.cc | 38 | ||||
-rw-r--r-- | src/arch/x86/predecoder.hh | 20 | ||||
-rw-r--r-- | src/arch/x86/predecoder_tables.cc | 2 | ||||
-rw-r--r-- | src/arch/x86/regfile.cc | 3 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 2 | ||||
-rw-r--r-- | src/cpu/simple/base.cc | 33 | ||||
-rw-r--r-- | src/cpu/simple/base.hh | 6 |
12 files changed, 614 insertions, 35 deletions
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index 2dfff8c5f..714bca22a 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -292,6 +292,10 @@ ITB::regStats() Fault ITB::translate(RequestPtr &req, ThreadContext *tc) const { + //If this is a pal pc, then set PHYSICAL + if(FULL_SYSTEM && PcPAL(req->getPC())) + req->setFlags(req->getFlags() | PHYSICAL); + if (PcPAL(req->getPC())) { // strip off PAL PC marker (lsb is 1) req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask); diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 6c8201f77..7edb9f3d7 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -194,7 +194,7 @@ def t_error(t): t.skip(1) # Build the lexer -lex.lex() +lexer = lex.lex() ##################################################################### # @@ -729,7 +729,7 @@ def p_error(t): # END OF GRAMMAR RULES # # Now build the parser. -yacc.yacc() +parser = yacc.yacc() ##################################################################### @@ -1881,7 +1881,8 @@ def parse_isa_desc(isa_desc_file, output_dir): fileNameStack.push((isa_desc_file, 0)) # Parse it. - (isa_name, namespace, global_code, namespace_code) = yacc.parse(isa_desc) + (isa_name, namespace, global_code, namespace_code) = \ + parser.parse(isa_desc, lexer=lexer) # grab the last three path components of isa_desc_file to put in # the output diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py new file mode 100644 index 000000000..3d9e83648 --- /dev/null +++ b/src/arch/micro_asm.py @@ -0,0 +1,433 @@ +# Copyright (c) 2003-2005 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 + +import os +import sys +import re +import string +import traceback +# get type names +from types import * + +# Prepend the directory where the PLY lex & yacc modules are found +# to the search path. +sys.path[0:0] = [os.environ['M5_PLY']] + +from ply import lex +from ply import yacc + +########################################################################## +# +# Base classes for use outside of the assembler +# +########################################################################## + +class Micro_Container(object): + def __init__(self, name): + self.microops = [] + self.name = name + self.directives = {} + self.micro_classes = {} + self.labels = {} + + def add_microop(self, microop): + self.microops.append(microop) + + def __str__(self): + string = "%s:\n" % self.name + for microop in self.microops: + string += " %s\n" % microop + return string + +class Macroop(Micro_Container): + pass + +class Rom(Micro_Container): + def __init__(self, name): + super(Rom, self).__init__(name) + self.externs = {} + +########################################################################## +# +# Support classes +# +########################################################################## + +class Label(object): + def __init__(self): + self.extern = False + self.name = "" + +class Block(object): + def __init__(self): + self.statements = [] + +class Statement(object): + def __init__(self): + self.is_microop = False + self.is_directive = False + +class Microop(Statement): + def __init__(self): + super(Microop, self).__init__() + self.mnemonic = "" + self.labels = [] + self.is_microop = True + self.params = "" + +class Directive(Statement): + def __init__(self): + super(Directive, self).__init__() + self.name = "" + self.is_directive = True + +########################################################################## +# +# Functions that handle common tasks +# +########################################################################## + +def print_error(message): + print + print "*** %s" % message + print + +def handle_statement(parser, container, statement): + if statement.is_microop: + try: + microop = eval('parser.microops[statement.mnemonic](%s)' % + statement.params) + except: + print_error("Error creating microop object.") + raise + try: + for label in statement.labels: + container.labels[label.name] = microop + if label.extern: + container.externs[label.name] = microop + container.add_microop(microop) + except: + print_error("Error adding microop.") + raise + elif statement.is_directive: + try: + eval('container.%s()' % statement.name) + except: + print_error("Error executing directive.") + print container.directives + raise + else: + raise Exception, "Didn't recognize the type of statement", statement + +########################################################################## +# +# Lexer specification +# +########################################################################## + +# Error handler. Just call exit. Output formatted to work under +# Emacs compile-mode. Optional 'print_traceback' arg, if set to True, +# prints a Python stack backtrace too (can be handy when trying to +# debug the parser itself). +def error(lineno, string, print_traceback = False): + # Print a Python stack backtrace if requested. + if (print_traceback): + traceback.print_exc() + if lineno != 0: + line_str = "%d:" % lineno + else: + line_str = "" + sys.exit("%s %s" % (line_str, string)) + +reserved = ('DEF', 'MACROOP', 'ROM', 'EXTERN') + +tokens = reserved + ( + # identifier + 'ID', + # arguments for microops and directives + 'PARAMS', + + 'LPAREN', 'RPAREN', + 'LBRACE', 'RBRACE', + #'COMMA', + 'COLON', 'SEMI', 'DOT', + 'NEWLINE' + ) + +# New lines are ignored at the top level, but they end statements in the +# assembler +states = ( + ('asm', 'exclusive'), + ('params', 'exclusive'), +) + +reserved_map = { } +for r in reserved: + reserved_map[r.lower()] = r + +def t_params_COLON(t): + r':' + t.lexer.begin('asm') + return t + +def t_asm_ID(t): + r'[A-Za-z_]\w*' + t.type = reserved_map.get(t.value, 'ID') + t.lexer.begin('params') + return t + +def t_ANY_ID(t): + r'[A-Za-z_]\w*' + t.type = reserved_map.get(t.value, 'ID') + return t + +def t_params_PARAMS(t): + r'([^\n;]|((?<=\\)[\n;]))+' + t.lineno += t.value.count('\n') + t.lexer.begin('asm') + return t + +def t_INITIAL_LBRACE(t): + r'\{' + t.lexer.begin('asm') + return t + +def t_asm_RBRACE(t): + r'\}' + t.lexer.begin('INITIAL') + return t + +def t_INITIAL_NEWLINE(t): + r'\n+' + t.lineno += t.value.count('\n') + +def t_asm_NEWLINE(t): + r'\n+' + t.lineno += t.value.count('\n') + return t + +def t_params_NEWLINE(t): + r'\n+' + t.lineno += t.value.count('\n') + t.lexer.begin('asm') + return t + +def t_params_SEMI(t): + r';' + t.lexer.begin('asm') + return t + +# Basic regular expressions to pick out simple tokens +t_ANY_LPAREN = r'\(' +t_ANY_RPAREN = r'\)' +#t_COMMA = r',' +t_ANY_SEMI = r';' +t_ANY_DOT = r'\.' + +t_ANY_ignore = ' \t\x0c' + +def t_ANY_error(t): + error(t.lineno, "illegal character '%s'" % t.value[0]) + t.skip(1) + +########################################################################## +# +# Parser specification +# +########################################################################## + +# Start symbol for a file which may have more than one macroop or rom +# specification. +def p_file(t): + 'file : opt_rom_or_macros' + +def p_opt_rom_or_macros_0(t): + 'opt_rom_or_macros : ' + +def p_opt_rom_or_macros_1(t): + 'opt_rom_or_macros : rom_or_macros' + +def p_rom_or_macros_0(t): + 'rom_or_macros : rom_or_macro' + +def p_rom_or_macros_1(t): + 'rom_or_macros : rom_or_macros rom_or_macro' + +def p_rom_or_macro_0(t): + '''rom_or_macro : rom_block''' + +def p_rom_or_macro_1(t): + '''rom_or_macro : macroop_def''' + +# A block of statements +def p_block(t): + 'block : LBRACE statements RBRACE' + block = Block() + block.statements = t[2] + t[0] = block + +# Defines a section of microcode that should go in the current ROM +def p_rom_block(t): + 'rom_block : DEF ROM block SEMI' + for statement in t[3].statements: + handle_statement(t.parser, t.parser.rom, statement) + t[0] = t.parser.rom + +# Defines a macroop that jumps to an external label in the ROM +def p_macroop_def_0(t): + 'macroop_def : DEF MACROOP LPAREN ID RPAREN SEMI' + t[0] = t[4] + +# Defines a macroop that is combinationally generated +def p_macroop_def_1(t): + 'macroop_def : DEF MACROOP ID block SEMI' + try: + curop = t.parser.macro_type(t[3]) + except TypeError: + print_error("Error creating macroop object.") + raise + for statement in t[4].statements: + handle_statement(t.parser, curop, statement) + t.parser.macroops.append(curop) + +def p_statements_0(t): + 'statements : statement' + if t[1]: + t[0] = [t[1]] + else: + t[0] = [] + +def p_statements_1(t): + 'statements : statements statement' + if t[2]: + t[1].append(t[2]) + t[0] = t[1] + +def p_statement(t): + 'statement : content_of_statement end_of_statement' + t[0] = t[1] + +# A statement can be a microop or an assembler directive +def p_content_of_statement_0(t): + '''content_of_statement : microop + | directive''' + t[0] = t[1] + +def p_content_of_statement_1(t): + 'content_of_statement : ' + pass + +# Statements are ended by newlines or a semi colon +def p_end_of_statement(t): + '''end_of_statement : NEWLINE + | SEMI''' + pass + +def p_microop_0(t): + 'microop : labels ID' + microop = Microop() + microop.labels = t[1] + microop.mnemonic = t[2] + t[0] = microop + +def p_microop_1(t): + 'microop : ID' + microop = Microop() + microop.mnemonic = t[1] + t[0] = microop + +def p_microop_2(t): + 'microop : labels ID PARAMS' + microop = Microop() + microop.labels = t[1] + microop.mnemonic = t[2] + microop.params = t[3] + t[0] = microop + +def p_microop_3(t): + 'microop : ID PARAMS' + microop = Microop() + microop.mnemonic = t[1] + microop.params = t[2] + t[0] = microop + +def p_labels_0(t): + 'labels : label' + t[0] = [t[1]] + +def p_labels_1(t): + 'labels : labels label' + t[1].append(t[2]) + t[0] = t[1] + +def p_label_0(t): + 'label : ID COLON' + label = Label() + label.is_extern = False + label.text = t[1] + t[0] = label + +def p_label_1(t): + 'label : EXTERN ID COLON' + label = Label() + label.is_extern = True + label.text = t[2] + t[0] = label + +def p_directive(t): + 'directive : DOT ID' + directive = Directive() + directive.name = t[2] + t[0] = directive + +# Parse error handler. Note that the argument here is the offending +# *token*, not a grammar symbol (hence the need to use t.value) +def p_error(t): + if t: + error(t.lineno, "syntax error at '%s'" % t.value) + else: + error(0, "unknown syntax error", True) + +class MicroAssembler(object): + + def __init__(self, macro_type, microops, rom): + self.lexer = lex.lex() + self.parser = yacc.yacc() + self.parser.macro_type = macro_type + self.parser.macroops = [] + self.parser.microops = microops + self.parser.rom = rom + + def assemble(self, asm): + self.parser.parse(asm, lexer=self.lexer) + for macroop in self.parser.macroops: + print macroop + print self.parser.rom + macroops = self.parser.macroops + self.parser.macroops = [] + return macroops diff --git a/src/arch/micro_asm_test.py b/src/arch/micro_asm_test.py new file mode 100755 index 000000000..4a643565c --- /dev/null +++ b/src/arch/micro_asm_test.py @@ -0,0 +1,91 @@ +# Copyright (c) 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: Gabe Black + +from micro_asm import MicroAssembler, Macroop, Rom + +class Bah(object): + def __init__(self): + self.mnemonic = "bah" + +class Bah_Tweaked(object): + def __init__(self): + self.mnemonic = "bah_tweaked" + +class Hoop(object): + def __init__(self, first_param, second_param): + self.mnemonic = "hoop_%s_%s" % (first_param, second_param) + def __str__(self): + return "%s" % self.mnemonic + +class Dah(object): + def __init__(self): + self.mnemonic = "dah" + +microops = { + "bah": Bah, + "hoop": Hoop, + "dah": Dah +} + +class TestMacroop(Macroop): + def tweak(self): + microops["bah"] = Bah_Tweaked + def untweak(self): + microops["bah"] = Bah + + def __init__(self, name): + super(TestMacroop, self).__init__(name) + self.directives = { + "tweak": self.tweak, + "untweak": self.untweak + } + +assembler = MicroAssembler(TestMacroop, microops, Rom('main ROM')) + +testAssembly = ''' +def rom { + goo: bah + extern la: hoop 4*8, "a" +}; + +def macroop squishy { + .tweak + bah + .untweak + bah + dah + .tweak +}; + +def macroop squashy { + bah +}; + +def macroop (bar); +''' +assembler.assemble(testAssembly) diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 4e044363b..12f3c5f96 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -237,11 +237,11 @@ 0x7: xchg_Ev_Gv(); } 0x11: decode OPCODE_OP_BOTTOM3 { - 0x0: Inst::MOV(); //mov_Eb_Gb(); - 0x1: Inst::MOV(); //mov_Ev_Gv(); - 0x2: Inst::MOV(); //mov_Gb_Eb(); - 0x3: Inst::MOV(); //mov_Gv_Ev(); - 0x4: Inst::MOV(); //mov_MwRv_Sw(); + 0x0: Inst::MOV(Eb, Gb); + 0x1: Inst::MOV(Ev, Gv); + 0x2: Inst::MOV(Gb, Eb); + 0x3: Inst::MOV(Gv, Ev); + 0x4: mov_MwRv_Sw(); //What to do with this one? 0x5: lea_Gv_M(); 0x6: mov_Sw_MwRv(); 0x7: group10_Ev(); //Make sure this is Ev diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index 573012ee6..65f951f44 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -62,6 +62,21 @@ namespace X86ISA { + void Predecoder::reset() + { + origPC = basePC + offset; + DPRINTF(Predecoder, "Setting origPC to %#x\n", origPC); + emi.opcode.num = 0; + + immediateCollected = 0; + emi.immediate = 0; + displacementCollected = 0; + emi.displacement = 0; + + emi.modRM = 0; + emi.sib = 0; + } + void Predecoder::process() { //This function drives the predecoder state machine. @@ -78,6 +93,9 @@ namespace X86ISA uint8_t nextByte = getNextByte(); switch(state) { + case ResetState: + reset(); + state = PrefixState; case PrefixState: state = doPrefixState(nextByte); break; @@ -150,7 +168,6 @@ namespace X86ISA emi.rex = nextByte; break; case 0: - emi.opcode.num = 0; nextState = OpcodeState; break; default: @@ -188,12 +205,6 @@ namespace X86ISA DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte); emi.opcode.op = nextByte; - //Prepare for any immediate/displacement we might need - immediateCollected = 0; - emi.immediate = 0; - displacementCollected = 0; - emi.displacement = 0; - //Figure out the effective operand size. This can be overriden to //a fixed value at the decoder level. if(/*FIXME long mode*/1) @@ -229,14 +240,11 @@ namespace X86ISA if (UsesModRM[emi.opcode.num - 1][nextByte]) { nextState = ModRMState; } else { - //If there's no modRM byte, set it to 0 so we can detect - //that later. - emi.modRM = 0; if(immediateSize) { nextState = ImmediateState; } else { emiIsReady = true; - nextState = PrefixState; + nextState = ResetState; } } } @@ -282,7 +290,7 @@ namespace X86ISA nextState = ImmediateState; } else { emiIsReady = true; - nextState = PrefixState; + nextState = ResetState; } //The ModRM byte is consumed no matter what consumeByte(); @@ -304,7 +312,7 @@ namespace X86ISA nextState = ImmediateState; } else { emiIsReady = true; - nextState = PrefixState; + nextState = ResetState; } return nextState; } @@ -344,7 +352,7 @@ namespace X86ISA nextState = ImmediateState; } else { emiIsReady = true; - nextState = PrefixState; + nextState = ResetState; } } else @@ -380,7 +388,7 @@ namespace X86ISA DPRINTF(Predecoder, "Collected immediate %#x.\n", emi.immediate); emiIsReady = true; - nextState = PrefixState; + nextState = ResetState; } else nextState = ImmediateState; diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh index 6562ab9f5..9b4d36d4a 100644 --- a/src/arch/x86/predecoder.hh +++ b/src/arch/x86/predecoder.hh @@ -60,6 +60,8 @@ #include "arch/x86/types.hh" #include "base/bitfield.hh" +#include "base/misc.hh" +#include "base/trace.hh" #include "sim/host.hh" class ThreadContext; @@ -81,6 +83,8 @@ namespace X86ISA MachInst fetchChunk; //The pc of the start of fetchChunk Addr basePC; + //The pc the current instruction started at + Addr origPC; //The offset into fetchChunk of current processing int offset; //The extended machine instruction being generated @@ -130,6 +134,8 @@ namespace X86ISA outOfBytes = true; } + void reset(); + //State machine state protected: //Whether or not we're out of bytes @@ -144,6 +150,7 @@ namespace X86ISA int immediateCollected; enum State { + ResetState, PrefixState, OpcodeState, ModRMState, @@ -166,9 +173,9 @@ namespace X86ISA public: Predecoder(ThreadContext * _tc) : - tc(_tc), basePC(0), offset(0), + tc(_tc), basePC(0), origPC(0), offset(0), outOfBytes(true), emiIsReady(false), - state(PrefixState) + state(ResetState) {} ThreadContext * getTC() @@ -219,6 +226,15 @@ namespace X86ISA emiIsReady = false; return emi; } + + int getInstSize() + { + DPRINTF(Predecoder, + "Calculating the instruction size: " + "basePC: %#x offset: %#x origPC: %#x\n", + basePC, offset, origPC); + return basePC + offset - origPC; + } }; }; diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc index 38b9c57a3..6fe54b719 100644 --- a/src/arch/x86/predecoder_tables.cc +++ b/src/arch/x86/predecoder_tables.cc @@ -170,7 +170,7 @@ namespace X86ISA // noimm byte word dword qword oword vword zword enter pointer {0, 1, 2, 4, 8, 16, 2, 2, 3, 4 }, //16 bit {0, 1, 2, 4, 8, 16, 4, 4, 3, 6 }, //32 bit - {0, 1, 2, 4, 8, 16, 4, 8, 3, 0 } //64 bit + {0, 1, 2, 4, 8, 16, 8, 4, 3, 0 } //64 bit }; //This table determines the immediate type. The first index is the diff --git a/src/arch/x86/regfile.cc b/src/arch/x86/regfile.cc index 568eb1d94..f54f531e2 100644 --- a/src/arch/x86/regfile.cc +++ b/src/arch/x86/regfile.cc @@ -117,7 +117,8 @@ void RegFile::setNextPC(Addr val) Addr RegFile::readNextNPC() { - return nextRip + sizeof(MachInst); + //There's no way to know how big the -next- instruction will be. + return nextRip + 1; } void RegFile::setNextNPC(Addr val) diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index b0a01c3a3..fab537748 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -557,7 +557,7 @@ AtomicSimpleCPU::tick() } } - if(predecoder.needMoreBytes() || fault != NoFault) + if(fault != NoFault || !stayAtPC) advancePC(fault); } diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index aa341487c..5e078c502 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -91,6 +91,9 @@ BaseSimpleCPU::BaseSimpleCPU(Params *p) lastDcacheStall = 0; threadContexts.push_back(tc); + + fetchOffset = 0; + stayAtPC = false; } BaseSimpleCPU::~BaseSimpleCPU() @@ -337,9 +340,9 @@ BaseSimpleCPU::setupFetchRequest(Request *req) thread->readNextPC()); #endif - req->setVirt(0, threadPC & ~3, sizeof(MachInst), - (FULL_SYSTEM && (threadPC & 1)) ? PHYSICAL : 0, - threadPC); + const Addr PCMask = ~(sizeof(MachInst) - 1); + Addr fetchPC = thread->readPC() + fetchOffset; + req->setVirt(0, fetchPC & PCMask, sizeof(MachInst), 0, threadPC()); Fault fault = thread->translateInstReq(req); @@ -367,21 +370,35 @@ BaseSimpleCPU::preExecute() // decode the instruction inst = gtoh(inst); + //If we're not in the middle of a macro instruction if (!curMacroStaticInst) { + StaticInstPtr instPtr = NULL; //Predecode, ie bundle up an ExtMachInst //This should go away once the constructor can be set up properly predecoder.setTC(thread->getTC()); //If more fetch data is needed, pass it in. + const Addr PCMask = ~(sizeof(MachInst) - 1); if(predecoder.needMoreBytes()) - predecoder.moreBytes(thread->readPC(), 0, inst); + predecoder.moreBytes((thread->readPC() & PCMask) + fetchOffset, + 0, inst); else predecoder.process(); - //If an instruction is ready, decode it - if (predecoder.extMachInstReady()) + + //If an instruction is ready, decode it. Otherwise, we'll have to + //fetch beyond the MachInst at the current pc. + if (predecoder.extMachInstReady()) { +#if THE_ISA == X86_ISA + thread->setNextPC(thread->readPC() + predecoder.getInstSize()); +#endif // X86_ISA + stayAtPC = false; instPtr = StaticInst::decode(predecoder.getExtMachInst()); + } else { + stayAtPC = true; + fetchOffset += sizeof(MachInst); + } //If we decoded an instruction and it's microcoded, start pulling //out micro ops @@ -451,12 +468,14 @@ BaseSimpleCPU::postExecute() void BaseSimpleCPU::advancePC(Fault fault) { + //Since we're moving to a new pc, zero out the offset + fetchOffset = 0; if (fault != NoFault) { curMacroStaticInst = StaticInst::nullStaticInstPtr; fault->invoke(tc); thread->setMicroPC(0); thread->setNextMicroPC(1); - } else if (predecoder.needMoreBytes()) { + } else { //If we're at the last micro op for this instruction if (curStaticInst && curStaticInst->isLastMicroOp()) { //We should be working with a macro op diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 787259c96..b25790e92 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -137,6 +137,12 @@ class BaseSimpleCPU : public BaseCPU StaticInstPtr curStaticInst; StaticInstPtr curMacroStaticInst; + //This is the offset from the current pc that fetch should be performed at + Addr fetchOffset; + //This flag says to stay at the current pc. This is useful for + //instructions which go beyond MachInst boundaries. + bool stayAtPC; + void checkForInterrupts(); Fault setupFetchRequest(Request *req); void preExecute(); |