summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/alpha/tlb.cc4
-rwxr-xr-xsrc/arch/isa_parser.py7
-rw-r--r--src/arch/micro_asm.py433
-rwxr-xr-xsrc/arch/micro_asm_test.py91
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa10
-rw-r--r--src/arch/x86/predecoder.cc38
-rw-r--r--src/arch/x86/predecoder.hh20
-rw-r--r--src/arch/x86/predecoder_tables.cc2
-rw-r--r--src/arch/x86/regfile.cc3
-rw-r--r--src/cpu/simple/atomic.cc2
-rw-r--r--src/cpu/simple/base.cc33
-rw-r--r--src/cpu/simple/base.hh6
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();