diff options
69 files changed, 4456 insertions, 1380 deletions
diff --git a/SConstruct b/SConstruct index ffcd84706..ec60964e4 100644 --- a/SConstruct +++ b/SConstruct @@ -67,7 +67,7 @@ import sys import os import subprocess -from os.path import join as joinpath +from os.path import isdir, join as joinpath # Check for recent-enough Python and SCons versions. If your system's # default installation of Python is not recent enough, you can use a @@ -97,6 +97,34 @@ SRCDIR = joinpath(ROOT, 'src') # tell python where to find m5 python code sys.path.append(joinpath(ROOT, 'src/python')) +def check_style_hook(ui): + ui.readconfig(joinpath(ROOT, '.hg', 'hgrc')) + style_hook = ui.config('hooks', 'pretxncommit.style', None) + + if not style_hook: + print """\ +You're missing the M5 style hook. +Please install the hook so we can ensure that all code fits a common style. + +All you'd need to do is add the following lines to your repository .hg/hgrc +or your personal .hgrc +---------------- + +[extensions] +style = %s/util/style.py + +[hooks] +pretxncommit.style = python:style.check_whitespace +""" % (ROOT) + sys.exit(1) + +if isdir(joinpath(ROOT, '.hg')): + try: + from mercurial import ui + check_style_hook(ui.ui()) + except ImportError: + pass + ################################################### # # Figure out which configurations to set up based on the path(s) of diff --git a/src/arch/alpha/faults.hh b/src/arch/alpha/faults.hh index 6342122c2..ed0c3a6b1 100644 --- a/src/arch/alpha/faults.hh +++ b/src/arch/alpha/faults.hh @@ -66,10 +66,10 @@ class MachineCheckFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} - bool isMachineCheckFault() {return true;} + bool isMachineCheckFault() const {return true;} }; class AlignmentFault : public AlphaFault @@ -79,10 +79,10 @@ class AlignmentFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} - bool isAlignmentFault() {return true;} + bool isAlignmentFault() const {return true;} }; static inline Fault genMachineCheckFault() @@ -102,7 +102,7 @@ class ResetFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -116,7 +116,7 @@ class ArithmeticFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} #if FULL_SYSTEM @@ -133,7 +133,7 @@ class InterruptFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -150,7 +150,7 @@ class DtbFault : public AlphaFault : vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags) { } #endif - FaultName name() = 0; + FaultName name() const = 0; FaultVect vect() = 0; FaultStat & countStat() = 0; #if FULL_SYSTEM @@ -170,7 +170,7 @@ class NDtbMissFault : public DtbFault : DtbFault(vaddr, reqFlags, flags) { } #endif - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -187,7 +187,7 @@ class PDtbMissFault : public DtbFault : DtbFault(vaddr, reqFlags, flags) { } #endif - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -204,7 +204,7 @@ class DtbPageFault : public DtbFault : DtbFault(vaddr, reqFlags, flags) { } #endif - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -221,7 +221,7 @@ class DtbAcvFault : public DtbFault : DtbFault(vaddr, reqFlags, flags) { } #endif - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -238,7 +238,7 @@ class DtbAlignmentFault : public DtbFault : DtbFault(vaddr, reqFlags, flags) { } #endif - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -251,7 +251,7 @@ class ItbFault : public AlphaFault ItbFault(Addr _pc) : pc(_pc) { } - FaultName name() = 0; + FaultName name() const = 0; FaultVect vect() = 0; FaultStat & countStat() = 0; #if FULL_SYSTEM @@ -269,7 +269,7 @@ class ItbMissFault : public ItbFault ItbMissFault(Addr pc) : ItbFault(pc) { } - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -284,7 +284,7 @@ class ItbPageFault : public ItbFault ItbPageFault(Addr pc) : ItbFault(pc) { } - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -299,7 +299,7 @@ class ItbAcvFault : public ItbFault ItbAcvFault(Addr pc) : ItbFault(pc) { } - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -311,7 +311,7 @@ class UnimplementedOpcodeFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -323,7 +323,7 @@ class FloatEnableFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -337,7 +337,7 @@ class PalFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -349,7 +349,7 @@ class IntegerOverflowFault : public AlphaFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 754a64fdb..64a120c4c 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -134,7 +134,7 @@ def t_INTLIT(t): try: t.value = int(t.value,0) except ValueError: - error(t.lineno, 'Integer value "%s" too large' % t.value) + error(t.lexer.lineno, 'Integer value "%s" too large' % t.value) t.value = 0 return t @@ -144,7 +144,7 @@ def t_STRLIT(t): r"(?m)'([^'])+'" # strip off quotes t.value = t.value[1:-1] - t.lineno += t.value.count('\n') + t.lexer.lineno += t.value.count('\n') return t @@ -154,22 +154,22 @@ def t_CODELIT(t): r"(?m)\{\{([^\}]|}(?!\}))+\}\}" # strip off {{ & }} t.value = t.value[2:-2] - t.lineno += t.value.count('\n') + t.lexer.lineno += t.value.count('\n') return t def t_CPPDIRECTIVE(t): r'^\#[^\#].*\n' - t.lineno += t.value.count('\n') + t.lexer.lineno += t.value.count('\n') return t def t_NEWFILE(t): r'^\#\#newfile\s+"[\w/.-]*"' - fileNameStack.push((t.value[11:-1], t.lineno)) - t.lineno = 0 + fileNameStack.push((t.value[11:-1], t.lexer.lineno)) + t.lexer.lineno = 0 def t_ENDFILE(t): r'^\#\#endfile' - (old_filename, t.lineno) = fileNameStack.pop() + (old_filename, t.lexer.lineno) = fileNameStack.pop() # # The functions t_NEWLINE, t_ignore, and t_error are @@ -179,7 +179,7 @@ def t_ENDFILE(t): # Newlines def t_NEWLINE(t): r'\n+' - t.lineno += t.value.count('\n') + t.lexer.lineno += t.value.count('\n') # Comments def t_comment(t): @@ -190,7 +190,7 @@ t_ignore = ' \t\x0c' # Error handler def t_error(t): - error(t.lineno, "illegal character '%s'" % t.value[0]) + error(t.lexer.lineno, "illegal character '%s'" % t.value[0]) t.skip(1) # Build the lexer @@ -318,7 +318,7 @@ def p_global_let(t): try: exec fixPythonIndentation(t[2]) in exportContext except Exception, exc: - error(t.lineno(1), + error(t.lexer.lineno, 'error: %s in global let block "%s".' % (exc, t[2])) t[0] = GenCode(header_output = exportContext["header_output"], decoder_output = exportContext["decoder_output"], @@ -332,9 +332,9 @@ def p_def_operand_types(t): try: userDict = eval('{' + t[3] + '}') except Exception, exc: - error(t.lineno(1), + error(t.lexer.lineno, 'error: %s in def operand_types block "%s".' % (exc, t[3])) - buildOperandTypeMap(userDict, t.lineno(1)) + buildOperandTypeMap(userDict, t.lexer.lineno) t[0] = GenCode() # contributes nothing to the output C++ file # Define the mapping from operand names to operand classes and other @@ -342,14 +342,14 @@ def p_def_operand_types(t): def p_def_operands(t): 'def_operands : DEF OPERANDS CODELIT SEMI' if not globals().has_key('operandTypeMap'): - error(t.lineno(1), + error(t.lexer.lineno, 'error: operand types must be defined before operands') try: userDict = eval('{' + t[3] + '}') except Exception, exc: - error(t.lineno(1), + error(t.lexer.lineno, 'error: %s in def operands block "%s".' % (exc, t[3])) - buildOperandNameMap(userDict, t.lineno(1)) + buildOperandNameMap(userDict, t.lexer.lineno) t[0] = GenCode() # contributes nothing to the output C++ file # A bitfield definition looks like: @@ -376,7 +376,7 @@ def p_def_bitfield_1(t): def p_def_bitfield_struct(t): 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' if (t[2] != ''): - error(t.lineno(1), 'error: structure bitfields are always unsigned.') + error(t.lexer.lineno, 'error: structure bitfields are always unsigned.') expr = 'machInst.%s' % t[5] hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) t[0] = GenCode(header_output = hash_define) @@ -410,7 +410,7 @@ def p_def_template(t): def p_def_format(t): 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' (id, params, code) = (t[3], t[5], t[7]) - defFormat(id, params, code, t.lineno(1)) + defFormat(id, params, code, t.lexer.lineno) t[0] = GenCode() # The formal parameter list for an instruction format is a possibly @@ -520,7 +520,7 @@ def p_decode_stmt_list_0(t): def p_decode_stmt_list_1(t): 'decode_stmt_list : decode_stmt decode_stmt_list' if (t[1].has_decode_default and t[2].has_decode_default): - error(t.lineno(1), 'Two default cases in decode block') + error(t.lexer.lineno, 'Two default cases in decode block') t[0] = t[1] + t[2] # @@ -565,7 +565,7 @@ def p_push_format_id(t): formatStack.push(formatMap[t[1]]) t[0] = ('', '// format %s' % t[1]) except KeyError: - error(t.lineno(1), 'instruction format "%s" not defined.' % t[1]) + error(t.lexer.lineno, 'instruction format "%s" not defined.' % t[1]) # Nested decode block: if the value of the current field matches the # specified constant, do a nested decode on some other field. @@ -617,7 +617,7 @@ def p_inst_0(t): 'inst : ID LPAREN arg_list RPAREN' # Pass the ID and arg list to the current format class to deal with. currentFormat = formatStack.top() - codeObj = currentFormat.defineInst(t[1], t[3], t.lineno(1)) + codeObj = currentFormat.defineInst(t[1], t[3], t.lexer.lineno) args = ','.join(map(str, t[3])) args = re.sub('(?m)^', '//', args) args = re.sub('^//', '', args) @@ -632,8 +632,8 @@ def p_inst_1(t): try: format = formatMap[t[1]] except KeyError: - error(t.lineno(1), 'instruction format "%s" not defined.' % t[1]) - codeObj = format.defineInst(t[3], t[5], t.lineno(1)) + error(t.lexer.lineno, 'instruction format "%s" not defined.' % t[1]) + codeObj = format.defineInst(t[3], t[5], t.lexer.lineno) comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) codeObj.prepend_all(comment) t[0] = codeObj @@ -722,7 +722,7 @@ def p_empty(t): # *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) + error(t.lexer.lineno, "syntax error at '%s'" % t.value) else: error(0, "unknown syntax error", True) diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh index 05a86acd7..2e5aa81d6 100644 --- a/src/arch/mips/faults.hh +++ b/src/arch/mips/faults.hh @@ -61,10 +61,10 @@ class MachineCheckFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} - bool isMachineCheckFault() {return true;} + bool isMachineCheckFault() const {return true;} }; class AlignmentFault : public MipsFault @@ -74,10 +74,10 @@ class AlignmentFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} - bool isAlignmentFault() {return true;} + bool isAlignmentFault() const {return true;} }; class UnimplementedOpcodeFault : public MipsFault @@ -87,7 +87,7 @@ class UnimplementedOpcodeFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -133,7 +133,7 @@ class ResetFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} void invoke(ThreadContext * tc); @@ -146,7 +146,7 @@ class CoprocessorUnusableFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} void invoke(ThreadContext * tc); @@ -159,7 +159,7 @@ class ReservedInstructionFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} void invoke(ThreadContext * tc); @@ -172,7 +172,7 @@ class ThreadFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} void invoke(ThreadContext * tc); @@ -188,7 +188,7 @@ class ArithmeticFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} #if FULL_SYSTEM @@ -205,7 +205,7 @@ class InterruptFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -217,7 +217,7 @@ class NDtbMissFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -229,7 +229,7 @@ class PDtbMissFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -241,7 +241,7 @@ class DtbPageFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -253,7 +253,7 @@ class DtbAcvFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -265,7 +265,7 @@ class ItbMissFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -277,7 +277,7 @@ class ItbPageFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -289,7 +289,7 @@ class ItbAcvFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -301,7 +301,7 @@ class FloatEnableFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -313,7 +313,7 @@ class IntegerOverflowFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} }; @@ -325,7 +325,7 @@ class DspStateDisabledFault : public MipsFault static FaultVect _vect; static FaultStat _count; public: - FaultName name() {return _name;} + FaultName name() const {return _name;} FaultVect vect() {return _vect;} FaultStat & countStat() {return _count;} void invoke(ThreadContext * tc); diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index 10ef89279..2456ad28a 100644 --- a/src/arch/sparc/faults.hh +++ b/src/arch/sparc/faults.hh @@ -65,7 +65,6 @@ class SparcFaultBase : public FaultBase #if FULL_SYSTEM void invoke(ThreadContext * tc); #endif - virtual FaultName name() = 0; virtual TrapType trapType() = 0; virtual FaultPriority priority() = 0; virtual FaultStat & countStat() = 0; @@ -78,7 +77,7 @@ class SparcFault : public SparcFaultBase protected: static FaultVals vals; public: - FaultName name() {return vals.name;} + FaultName name() const {return vals.name;} TrapType trapType() {return vals.trapType;} FaultPriority priority() {return vals.priority;} FaultStat & countStat() {return vals.count;} @@ -133,7 +132,7 @@ class InternalProcessorError : public SparcFault<InternalProcessorError> { public: - bool isMachineCheckFault() {return true;} + bool isMachineCheckFault() const {return true;} }; class InstructionInvalidTSBEntry : public SparcFault<InstructionInvalidTSBEntry> {}; @@ -152,7 +151,7 @@ class MemAddressNotAligned : public SparcFault<MemAddressNotAligned> { public: - bool isAlignmentFault() {return true;} + bool isAlignmentFault() const {return true;} }; class LDDFMemAddressNotAligned : public SparcFault<LDDFMemAddressNotAligned> {}; diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript index 6de243c9c..e8f8059ce 100644 --- a/src/arch/x86/SConscript +++ b/src/arch/x86/SConscript @@ -87,6 +87,9 @@ Import('*') if env['TARGET_ISA'] == 'x86': Source('emulenv.cc') Source('floatregfile.cc') + Source('insts/microldstop.cc') + Source('insts/microregop.cc') + Source('insts/static_inst.cc') Source('intregfile.cc') Source('miscregfile.cc') Source('predecoder.cc') diff --git a/src/arch/x86/emulenv.cc b/src/arch/x86/emulenv.cc index e3f703cff..3a54d7365 100644 --- a/src/arch/x86/emulenv.cc +++ b/src/arch/x86/emulenv.cc @@ -66,8 +66,8 @@ void EmulEnv::doModRM(const ExtMachInst & machInst) //Use the SIB byte for addressing if the modrm byte calls for it. if (machInst.modRM.rm == 4 && machInst.addrSize != 2) { scale = 1 << machInst.sib.scale; - index = machInst.sib.index; - base = machInst.sib.base; + index = machInst.sib.index | (machInst.rex.x << 3); + base = machInst.sib.base | (machInst.rex.b << 3); //In this special case, we don't use a base. The displacement also //changes, but that's managed by the predecoder. if (machInst.sib.base == INTREG_RBP && machInst.modRM.mod == 0) @@ -80,11 +80,13 @@ void EmulEnv::doModRM(const ExtMachInst & machInst) warn("I'm not really using 16 bit MODRM like I'm supposed to!\n"); } else { scale = 0; - base = machInst.modRM.rm; + base = machInst.modRM.rm | (machInst.rex.b << 3); if (machInst.modRM.mod == 0 && machInst.modRM.rm == 5) { base = NUM_INTREGS; - if (machInst.mode.submode == SixtyFourBitMode) - base = NUM_INTREGS+7; + //Since we need to use a different encoding of this + //instruction anyway, just ignore the base in those cases +// if (machInst.mode.submode == SixtyFourBitMode) +// base = NUM_INTREGS+7; } } } diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh index 8c9afcdb5..51c34cebd 100644 --- a/src/arch/x86/faults.hh +++ b/src/arch/x86/faults.hh @@ -66,7 +66,7 @@ namespace X86ISA class X86Fault : public FaultBase { protected: - const char * name() + const char * name() const { return "generic_x86_fault"; } @@ -80,7 +80,7 @@ namespace X86ISA class UnimpInstFault : public FaultBase { public: - const char * name() + const char * name() const { return "unimplemented_micro"; } diff --git a/src/arch/x86/insts/microldstop.cc b/src/arch/x86/insts/microldstop.cc new file mode 100644 index 000000000..8a52ad932 --- /dev/null +++ b/src/arch/x86/insts/microldstop.cc @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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 + */ + +#include "arch/x86/insts/microldstop.hh" +#include <string> + +namespace X86ISA +{ + std::string LdStOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + printReg(response, data, dataSize); + response << ", "; + printSegment(response, segment); + ccprintf(response, ":[%d*", scale); + printReg(response, index, addressSize); + response << " + "; + printReg(response, base, addressSize); + ccprintf(response, " + %#x]", disp); + return response.str(); + } +} diff --git a/src/arch/x86/insts/microldstop.hh b/src/arch/x86/insts/microldstop.hh new file mode 100644 index 000000000..f90d6670e --- /dev/null +++ b/src/arch/x86/insts/microldstop.hh @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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 + */ + +#ifndef __ARCH_X86_INSTS_MICROLDSTOP_HH__ +#define __ARCH_X86_INSTS_MICROLDSTOP_HH__ + +#include "arch/x86/insts/microop.hh" + +namespace X86ISA +{ + /** + * Base class for load and store ops + */ + class LdStOp : public X86MicroopBase + { + protected: + const uint8_t scale; + const RegIndex index; + const RegIndex base; + const uint64_t disp; + const uint8_t segment; + const RegIndex data; + const uint8_t dataSize; + const uint8_t addressSize; + + //Constructor + LdStOp(ExtMachInst _machInst, + const char * mnem, const char * _instMnem, + bool isMicro, bool isDelayed, bool isFirst, bool isLast, + uint8_t _scale, RegIndex _index, RegIndex _base, + uint64_t _disp, uint8_t _segment, + RegIndex _data, + uint8_t _dataSize, uint8_t _addressSize, + OpClass __opClass) : + X86MicroopBase(machInst, mnem, _instMnem, + isMicro, isDelayed, isFirst, isLast, __opClass), + scale(_scale), index(_index), base(_base), + disp(_disp), segment(_segment), + data(_data), + dataSize(_dataSize), addressSize(_addressSize) + {} + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +} + +#endif //__ARCH_X86_INSTS_MICROLDSTOP_HH__ diff --git a/src/arch/x86/insts/microop.hh b/src/arch/x86/insts/microop.hh new file mode 100644 index 000000000..45e1cb5c8 --- /dev/null +++ b/src/arch/x86/insts/microop.hh @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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 + */ + +#ifndef __ARCH_X86_INSTS_MICROOP_HH__ +#define __ARCH_X86_INSTS_MICROOP_HH__ + +#include "arch/x86/insts/static_inst.hh" + +namespace X86ISA +{ + //A class which is the base of all x86 micro ops. It provides a function to + //set necessary flags appropriately. + class X86MicroopBase : public X86StaticInst + { + protected: + const char * instMnem; + uint8_t opSize; + uint8_t addrSize; + + X86MicroopBase(ExtMachInst _machInst, + const char *mnem, const char *_instMnem, + bool isMicro, bool isDelayed, + bool isFirst, bool isLast, + OpClass __opClass) : + X86ISA::X86StaticInst(mnem, _machInst, __opClass), + instMnem(_instMnem) + { + flags[IsMicroop] = isMicro; + flags[IsDelayedCommit] = isDelayed; + flags[IsFirstMicroop] = isFirst; + flags[IsLastMicroop] = isLast; + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "\t%s.%s", instMnem, mnemonic); + + return ss.str(); + } + }; +} + +#endif //__ARCH_X86_INSTS_MICROOP_HH__ diff --git a/src/arch/x86/insts/microregop.cc b/src/arch/x86/insts/microregop.cc new file mode 100644 index 000000000..976b04688 --- /dev/null +++ b/src/arch/x86/insts/microregop.cc @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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 + */ + +#include "arch/x86/insts/microregop.hh" +#include "arch/x86/miscregs.hh" +#include "base/condcodes.hh" +#include <string> + +namespace X86ISA +{ + uint64_t RegOpBase::genFlags(uint64_t oldFlags, uint64_t flagMask, + uint64_t _dest, uint64_t _src1, uint64_t _src2, + bool subtract) const + { + DPRINTF(Sparc, "flagMask = %#x\n", flagMask); + uint64_t flags = oldFlags & ~flagMask; + if(flagMask & CFBit) + if(findCarry(dataSize*8, _dest, _src1, _src2)) + flags |= CFBit; + if(subtract) + flags ^= CFBit; + if(flagMask & PFBit && findParity(dataSize*8, _dest)) + flags |= PFBit; + if(flagMask & ECFBit && findCarry(dataSize*8, _dest, _src1, _src2)) + flags |= ECFBit; + if(flagMask & AFBit) + if(findCarry(4, _dest, _src1, _src2)) + flags |= AFBit; + if(subtract) + flags ^= AFBit; + if(flagMask & EZFBit && findZero(dataSize*8, _dest)) + flags |= EZFBit; + if(flagMask & ZFBit && findZero(dataSize*8, _dest)) + flags |= ZFBit; + if(flagMask & SFBit && findNegative(dataSize*8, _dest)) + flags |= SFBit; + if(flagMask & OFBit && findOverflow(dataSize*8, _dest, _src1, _src2)) + flags |= OFBit; + return flags; + } + + bool RegOpBase::checkCondition(uint64_t flags) const + { + CCFlagBits ccflags = flags; + switch(ext) + { + case ConditionTests::True: + return true; + case ConditionTests::ECF: + return ccflags.ECF; + case ConditionTests::EZF: + return ccflags.EZF; + case ConditionTests::SZnZF: + return !(!ccflags.EZF & ccflags.ZF); + case ConditionTests::MSTRZ: + panic("This condition is not implemented!"); + case ConditionTests::STRZ: + panic("This condition is not implemented!"); + case ConditionTests::MSTRC: + panic("This condition is not implemented!"); + case ConditionTests::STRZnZF: + panic("This condition is not implemented!"); + case ConditionTests::OF: + return ccflags.OF; + case ConditionTests::CF: + return ccflags.CF; + case ConditionTests::ZF: + return ccflags.ZF; + case ConditionTests::CvZF: + return ccflags.CF | ccflags.ZF; + case ConditionTests::SF: + return ccflags.SF; + case ConditionTests::PF: + return ccflags.PF; + case ConditionTests::SxOF: + return ccflags.SF ^ ccflags.OF; + case ConditionTests::SxOvZF: + return ccflags.SF ^ ccflags.OF | ccflags.ZF; + case ConditionTests::False: + return false; + case ConditionTests::NotECF: + return !ccflags.ECF; + case ConditionTests::NotEZF: + return !ccflags.EZF; + case ConditionTests::NotSZnZF: + return !ccflags.EZF & ccflags.ZF; + case ConditionTests::NotMSTRZ: + panic("This condition is not implemented!"); + case ConditionTests::NotSTRZ: + panic("This condition is not implemented!"); + case ConditionTests::NotMSTRC: + panic("This condition is not implemented!"); + case ConditionTests::NotSTRZnZF: + panic("This condition is not implemented!"); + case ConditionTests::NotOF: + return !ccflags.OF; + case ConditionTests::NotCF: + return !ccflags.CF; + case ConditionTests::NotZF: + return !ccflags.ZF; + case ConditionTests::NotCvZF: + return !(ccflags.CF | ccflags.ZF); + case ConditionTests::NotSF: + return !ccflags.SF; + case ConditionTests::NotPF: + return !ccflags.PF; + case ConditionTests::NotSxOF: + return !(ccflags.SF ^ ccflags.OF); + case ConditionTests::NotSxOvZF: + return !(ccflags.SF ^ ccflags.OF | ccflags.ZF); + } + panic("Unknown condition: %d\n", ext); + return true; + } + + std::string RegOp::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + printReg(response, dest, dataSize); + response << ", "; + printReg(response, src1, dataSize); + response << ", "; + printReg(response, src2, dataSize); + return response.str(); + } + + std::string RegOpImm::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + printReg(response, dest, dataSize); + response << ", "; + printReg(response, src1, dataSize); + ccprintf(response, ", %#x", imm8); + return response.str(); + } +} diff --git a/src/arch/x86/insts/microregop.hh b/src/arch/x86/insts/microregop.hh new file mode 100644 index 000000000..f411c0775 --- /dev/null +++ b/src/arch/x86/insts/microregop.hh @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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 + */ + +#ifndef __ARCH_X86_INSTS_MICROREGOP_HH__ +#define __ARCH_X86_INSTS_MICROREGOP_HH__ + +#include "arch/x86/insts/microop.hh" + +namespace X86ISA +{ + namespace ConditionTests + { + enum CondTest { + True, + NotFalse = True, + ECF, + EZF, + SZnZF, + MSTRZ, + STRZ, + MSTRC, + STRZnZF, + OF, + CF, + ZF, + CvZF, + SF, + PF, + SxOF, + SxOvZF, + + False, + NotTrue = False, + NotECF, + NotEZF, + NotSZnZF, + NotMSTRZ, + NotSTRZ, + NotMSTRC, + NotSTRZnZF, + NotOF, + NotCF, + NotZF, + NotCvZF, + NotSF, + NotPF, + NotSxOF, + NotSxOvZF + }; + } + + /** + * Base classes for RegOps which provides a generateDisassembly method. + */ + class RegOpBase : public X86MicroopBase + { + protected: + const RegIndex src1; + const RegIndex dest; + const uint8_t dataSize; + const uint16_t ext; + + // Constructor + RegOpBase(ExtMachInst _machInst, + const char *mnem, const char *_instMnem, + bool isMicro, bool isDelayed, + bool isFirst, bool isLast, + RegIndex _src1, RegIndex _dest, + uint8_t _dataSize, uint16_t _ext, + OpClass __opClass) : + X86MicroopBase(_machInst, mnem, _instMnem, + isMicro, isDelayed, isFirst, isLast, + __opClass), + src1(_src1), dest(_dest), + dataSize(_dataSize), ext(_ext) + { + } + + //Figure out what the condition code flags should be. + uint64_t genFlags(uint64_t oldFlags, uint64_t flagMask, + uint64_t _dest, uint64_t _src1, uint64_t _src2, + bool subtract = false) const; + bool checkCondition(uint64_t flags) const; + }; + + class RegOp : public RegOpBase + { + protected: + const RegIndex src2; + + // Constructor + RegOp(ExtMachInst _machInst, + const char *mnem, const char *_instMnem, + bool isMicro, bool isDelayed, + bool isFirst, bool isLast, + RegIndex _src1, RegIndex _src2, RegIndex _dest, + uint8_t _dataSize, uint16_t _ext, + OpClass __opClass) : + RegOpBase(_machInst, mnem, _instMnem, + isMicro, isDelayed, isFirst, isLast, + _src1, _dest, _dataSize, _ext, + __opClass), + src2(_src2) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; + + class RegOpImm : public RegOpBase + { + protected: + const uint8_t imm8; + + // Constructor + RegOpImm(ExtMachInst _machInst, + const char * mnem, const char *_instMnem, + bool isMicro, bool isDelayed, + bool isFirst, bool isLast, + RegIndex _src1, uint8_t _imm8, RegIndex _dest, + uint8_t _dataSize, uint16_t _ext, + OpClass __opClass) : + RegOpBase(_machInst, mnem, _instMnem, + isMicro, isDelayed, isFirst, isLast, + _src1, _dest, _dataSize, _ext, + __opClass), + imm8(_imm8) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +} + +#endif //__ARCH_X86_INSTS_MICROREGOP_HH__ diff --git a/src/arch/x86/insts/static_inst.cc b/src/arch/x86/insts/static_inst.cc new file mode 100644 index 000000000..9b2f81e49 --- /dev/null +++ b/src/arch/x86/insts/static_inst.cc @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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 + */ + +#include "arch/x86/insts/static_inst.hh" + +namespace X86ISA +{ + void X86StaticInst::printMnemonic(std::ostream &os, + const char * mnemonic) const + { + ccprintf(os, "\t%s ", mnemonic); + } + + void X86StaticInst::printMnemonic(std::ostream &os, + const char * instMnemonic, const char * mnemonic) const + { + ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic); + } + + void X86StaticInst::printSegment(std::ostream &os, int segment) const + { + switch (segment) + { + case 0: + ccprintf(os, "ES"); + break; + case 1: + ccprintf(os, "CS"); + break; + case 2: + ccprintf(os, "SS"); + break; + case 3: + ccprintf(os, "DS"); + break; + case 4: + ccprintf(os, "FS"); + break; + case 5: + ccprintf(os, "GS"); + break; + default: + panic("Unrecognized segment %d\n", segment); + } + } + + void + X86StaticInst::printSrcReg(std::ostream &os, int reg, int size) const + { + if(_numSrcRegs > reg) + printReg(os, _srcRegIdx[reg], size); + } + + void + X86StaticInst::printDestReg(std::ostream &os, int reg, int size) const + { + if(_numDestRegs > reg) + printReg(os, _destRegIdx[reg], size); + } + + void + X86StaticInst::printReg(std::ostream &os, int reg, int size) const + { + assert(size == 1 || size == 2 || size == 4 || size == 8); + static const char * abcdFormats[9] = + {"", "%sl", "%sx", "", "e%sx", "", "", "", "r%sx"}; + static const char * piFormats[9] = + {"", "%sl", "%s", "", "e%s", "", "", "", "r%s"}; + static const char * longFormats[9] = + {"", "r%sb", "r%sw", "", "r%sd", "", "", "", "r%s"}; + static const char * microFormats[9] = + {"", "t%db", "t%dw", "", "t%dd", "", "", "", "t%d"}; + + if (reg < FP_Base_DepTag) { + switch (reg) { + case INTREG_RAX: + ccprintf(os, abcdFormats[size], "a"); + break; + case INTREG_RBX: + ccprintf(os, abcdFormats[size], "b"); + break; + case INTREG_RCX: + ccprintf(os, abcdFormats[size], "c"); + break; + case INTREG_RDX: + ccprintf(os, abcdFormats[size], "d"); + break; + case INTREG_RSP: + ccprintf(os, piFormats[size], "sp"); + break; + case INTREG_RBP: + ccprintf(os, piFormats[size], "bp"); + break; + case INTREG_RSI: + ccprintf(os, piFormats[size], "si"); + break; + case INTREG_RDI: + ccprintf(os, piFormats[size], "di"); + break; + case INTREG_R8W: + ccprintf(os, longFormats[size], "8"); + break; + case INTREG_R9W: + ccprintf(os, longFormats[size], "9"); + break; + case INTREG_R10W: + ccprintf(os, longFormats[size], "10"); + break; + case INTREG_R11W: + ccprintf(os, longFormats[size], "11"); + break; + case INTREG_R12W: + ccprintf(os, longFormats[size], "12"); + break; + case INTREG_R13W: + ccprintf(os, longFormats[size], "13"); + break; + case INTREG_R14W: + ccprintf(os, longFormats[size], "14"); + break; + case INTREG_R15W: + ccprintf(os, longFormats[size], "15"); + break; + default: + ccprintf(os, microFormats[size], reg - NUM_INTREGS); + } + } else if (reg < Ctrl_Base_DepTag) { + ccprintf(os, "%%f%d", reg - FP_Base_DepTag); + } else { + switch (reg - Ctrl_Base_DepTag) { + default: + ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); + } + } + } + + std::string X86StaticInst::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream ss; + + printMnemonic(ss, mnemonic); + + return ss.str(); + } +} diff --git a/src/arch/x86/insts/static_inst.hh b/src/arch/x86/insts/static_inst.hh new file mode 100644 index 000000000..c39c2956e --- /dev/null +++ b/src/arch/x86/insts/static_inst.hh @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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 + */ + +#ifndef __ARCH_X86_INSTS_STATICINST_HH__ +#define __ARCH_X86_INSTS_STATICINST_HH__ + +#include "cpu/static_inst.hh" + +namespace X86ISA +{ + /** + * Base class for all X86 static instructions. + */ + + class X86StaticInst : public StaticInst + { + protected: + // Constructor. + X86StaticInst(const char *mnem, + ExtMachInst _machInst, OpClass __opClass) + : StaticInst(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + void printMnemonic(std::ostream &os, const char * mnemonic) const; + void printMnemonic(std::ostream &os, const char * instMnemonic, + const char * mnemonic) const; + + void printSegment(std::ostream &os, int segment) const; + + void printReg(std::ostream &os, int reg, int size) const; + void printSrcReg(std::ostream &os, int reg, int size) const; + void printDestReg(std::ostream &os, int reg, int size) const; + + inline uint64_t merge(uint64_t into, uint64_t val, int size) const + { + X86IntReg reg; + reg = into; + //FIXME This needs to be handle high bytes as well + switch(size) + { + case 1: + reg.L = val; + break; + case 2: + reg.X = val; + break; + case 4: + //XXX Check if this should be zeroed or sign extended + reg = 0; + reg.E = val; + break; + case 8: + reg.R = val; + break; + default: + panic("Tried to merge with unrecognized size %d.\n", size); + } + return val; + } + + inline uint64_t pick(uint64_t from, int size) + { + X86IntReg reg; + reg = from; + switch(size) + { + case 1: + return reg.L; + case 2: + return reg.E; + case 4: + return reg.X; + case 8: + return reg.R; + default: + panic("Tried to pick with unrecognized size %d.\n", size); + } + } + }; +} + +#endif //__ARCH_X86_INSTS_STATICINST_HH__ diff --git a/src/arch/x86/intregfile.hh b/src/arch/x86/intregfile.hh index f7b03f0f0..be6242a41 100644 --- a/src/arch/x86/intregfile.hh +++ b/src/arch/x86/intregfile.hh @@ -104,7 +104,8 @@ namespace X86ISA std::string getIntRegName(RegIndex); const int NumIntArchRegs = NUM_INTREGS; - const int NumIntRegs = NumIntArchRegs + NumMicroIntRegs; + const int NumIntRegs = + NumIntArchRegs + NumMicroIntRegs + NumPseudoIntRegs; class IntRegFile { diff --git a/src/arch/x86/intregs.hh b/src/arch/x86/intregs.hh index 1b5777f01..bfec7d041 100644 --- a/src/arch/x86/intregs.hh +++ b/src/arch/x86/intregs.hh @@ -58,8 +58,18 @@ #ifndef __ARCH_X86_INTREGS_HH__ #define __ARCH_X86_INTREGS_HH__ +#include "base/bitunion.hh" + namespace X86ISA { + BitUnion64(X86IntReg) + Bitfield<63,0> R; + Bitfield<31,0> E; + Bitfield<15,0> X; + Bitfield<15,8> H; + Bitfield<7, 0> L; + EndBitUnion(X86IntReg) + enum IntRegIndex { INTREG_RAX, diff --git a/src/arch/x86/isa/base.isa b/src/arch/x86/isa/base.isa deleted file mode 100644 index eed969b47..000000000 --- a/src/arch/x86/isa/base.isa +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (c) 2007 The Hewlett-Packard Development Company -// All rights reserved. -// -// Redistribution and use of this software in source and binary forms, -// with or without modification, are permitted provided that the -// following conditions are met: -// -// The software must be used only for Non-Commercial Use which means any -// use which is NOT directed to receiving any direct monetary -// compensation for, or commercial advantage from such use. Illustrative -// examples of non-commercial use are academic research, personal study, -// teaching, education and corporate research & development. -// Illustrative examples of commercial use are distributing products for -// commercial advantage and providing services using the software for -// commercial advantage. -// -// If you wish to use this software or functionality therein that may be -// covered by patents for commercial use, please contact: -// Director of Intellectual Property Licensing -// Office of Strategy and Technology -// Hewlett-Packard Company -// 1501 Page Mill Road -// Palo Alto, California 94304 -// -// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. No right of -// sublicense is granted herewith. Derivatives of the software and -// output created using the software may be prepared, but only for -// Non-Commercial Uses. Derivatives of the software may be shared with -// others provided: (i) the others agree to abide by the list of -// conditions herein which includes the Non-Commercial Use restrictions; -// and (ii) such Derivatives of the software include the above copyright -// notice to acknowledge the contribution from this software where -// applicable, this list of conditions and the disclaimer below. -// -// 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 - -//////////////////////////////////////////////////////////////////// -// -// Base class for sparc instructions, and some support functions -// - -let {{ - # This class will help make dealing with output a little less verbose - class OutputBlocks(object): - def __init__(self, header_output="", - decoder_output="", - decode_block="", - exec_output=""): - self.header_output = header_output - self.decoder_output = decoder_output - self.decode_block = decode_block - self.exec_output = exec_output - - def append(self, blocks): - if isinstance(blocks, list) or isinstance(blocks, tuple): - assert(len(blocks) == 4) - self.header_output += blocks[0] - self.decoder_output += blocks[1] - self.decode_block += blocks[2] - self.exec_output += blocks[3] - else: - self.header_output += blocks.header_output - self.decoder_output += blocks.decoder_output - self.decode_block += blocks.decode_block - self.exec_output += blocks.exec_output - - def makeList(self): - return (self.header_output, - self.decoder_output, - self.decode_block, - self.exec_output) -}}; - -output header {{ - - /** - * Base class for all X86 static instructions. - */ - BitUnion64(X86IntReg) - Bitfield<63,0> R; - Bitfield<31,0> E; - Bitfield<15,0> X; - Bitfield<15,8> H; - Bitfield<7, 0> L; - EndBitUnion(X86IntReg) - - class X86StaticInst : public StaticInst - { - protected: - // Constructor. - X86StaticInst(const char *mnem, - ExtMachInst _machInst, OpClass __opClass) - : StaticInst(mnem, _machInst, __opClass) - { - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - - void printReg(std::ostream &os, int reg) const; - void printSrcReg(std::ostream &os, int reg) const; - void printDestReg(std::ostream &os, int reg) const; - - inline uint64_t merge(uint64_t into, uint64_t val, int size) const - { - X86IntReg reg; - reg = into; - //FIXME This needs to be handle high bytes as well - switch(size) - { - case 1: - reg.L = val; - break; - case 2: - reg.X = val; - break; - case 4: - //XXX Check if this should be zeroed or sign extended - reg = 0; - reg.E = val; - break; - case 8: - reg.R = val; - break; - default: - panic("Tried to merge with unrecognized size %d.\n", size); - } - return val; - } - - inline uint64_t pick(uint64_t from, int size) - { - X86IntReg reg; - reg = from; - switch(size) - { - case 1: - return reg.L; - case 2: - return reg.E; - case 4: - return reg.X; - case 8: - return reg.R; - default: - panic("Tried to pick with unrecognized size %d.\n", size); - } - } - - }; -}}; - -output decoder {{ - - inline void printMnemonic(std::ostream &os, const char * mnemonic) - { - ccprintf(os, "\t%s ", mnemonic); - } - - inline void printMnemonic(std::ostream &os, - const char * instMnemonic, const char * mnemonic) - { - ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic); - } - - void printSegment(std::ostream &os, int segment) - { - switch (segment) - { - case 0: - ccprintf(os, "ES"); - break; - case 1: - ccprintf(os, "CS"); - break; - case 2: - ccprintf(os, "SS"); - break; - case 3: - ccprintf(os, "DS"); - break; - case 4: - ccprintf(os, "FS"); - break; - case 5: - ccprintf(os, "GS"); - break; - default: - panic("Unrecognized segment %d\n", segment); - } - } - - void - X86StaticInst::printSrcReg(std::ostream &os, int reg) const - { - if(_numSrcRegs > reg) - printReg(os, _srcRegIdx[reg]); - } - - void - X86StaticInst::printDestReg(std::ostream &os, int reg) const - { - if(_numDestRegs > reg) - printReg(os, _destRegIdx[reg]); - } - - void - X86StaticInst::printReg(std::ostream &os, int reg) const - { - if (reg < FP_Base_DepTag) { - //FIXME These should print differently depending on the - //mode etc, but for now this will get the point across - switch (reg) { - case INTREG_RAX: - ccprintf(os, "rax"); - break; - case INTREG_RBX: - ccprintf(os, "rbx"); - break; - case INTREG_RCX: - ccprintf(os, "rcx"); - break; - case INTREG_RDX: - ccprintf(os, "rdx"); - break; - case INTREG_RSP: - ccprintf(os, "rsp"); - break; - case INTREG_RBP: - ccprintf(os, "rbp"); - break; - case INTREG_RSI: - ccprintf(os, "rsi"); - break; - case INTREG_RDI: - ccprintf(os, "rdi"); - break; - case INTREG_R8W: - ccprintf(os, "r8"); - break; - case INTREG_R9W: - ccprintf(os, "r9"); - break; - case INTREG_R10W: - ccprintf(os, "r10"); - break; - case INTREG_R11W: - ccprintf(os, "r11"); - break; - case INTREG_R12W: - ccprintf(os, "r12"); - break; - case INTREG_R13W: - ccprintf(os, "r13"); - break; - case INTREG_R14W: - ccprintf(os, "r14"); - break; - case INTREG_R15W: - ccprintf(os, "r15"); - break; - default: - ccprintf(os, "t%d", reg - NUM_INTREGS); - } - } else if (reg < Ctrl_Base_DepTag) { - ccprintf(os, "%%f%d", reg - FP_Base_DepTag); - } else { - switch (reg - Ctrl_Base_DepTag) { - default: - ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag); - } - } - } - - std::string X86StaticInst::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream ss; - - printMnemonic(ss, mnemonic); - - return ss.str(); - } -}}; diff --git a/src/arch/x86/isa/bitfields.isa b/src/arch/x86/isa/bitfields.isa index 8707bbb4c..43fee5fef 100644 --- a/src/arch/x86/isa/bitfields.isa +++ b/src/arch/x86/isa/bitfields.isa @@ -67,11 +67,12 @@ def bitfield REX_B rex.b; //Legacy prefixes def bitfield LEGACY legacy; +def bitfield LEGACY_DECODEVAL legacy.decodeVal; def bitfield LEGACY_REPNE legacy.repne; def bitfield LEGACY_REP legacy.rep; def bitfield LEGACY_LOCK legacy.lock; -def bitfield LEGACY_ADDR legacy.addr; def bitfield LEGACY_OP legacy.op; +def bitfield LEGACY_ADDR legacy.addr; def bitfield LEGACY_SEG legacy.seg; // Pieces of the opcode diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 484f8160d..b28f2029c 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -61,178 +61,130 @@ 0x1: decode OPCODE_OP_TOP5 { format WarnUnimpl { 0x00: decode OPCODE_OP_BOTTOM3 { - 0x4: ADD(); - 0x5: ADD(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: push_ES(); } 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: pop_ES(); } - default: ADD(); + default: MultiInst::ADD(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x01: decode OPCODE_OP_BOTTOM3 { - 0x0: or_Eb_Gb(); - 0x1: or_Ev_Gv(); - 0x2: or_Gb_Eb(); - 0x3: or_Gv_Ev(); - 0x4: or_Al_Ib(); - 0x5: or_rAX_Iz(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: push_CS(); } //Any time this is seen, it should generate a two byte opcode 0x7: M5InternalError::error( {{"Saw a one byte opcode whose value was 0x0F!"}}); + default: MultiInst::OR(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x02: decode OPCODE_OP_BOTTOM3 { - 0x0: adc_Eb_Gb(); - 0x1: adc_Ev_Gv(); - 0x2: adc_Gb_Eb(); - 0x3: adc_Gv_Ev(); - 0x4: adc_Al_Ib(); - 0x5: adc_rAX_Iz(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: push_SS(); } 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: pop_SS(); } + default: MultiInst::ADC(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x03: decode OPCODE_OP_BOTTOM3 { - 0x0: sbb_Eb_Gb(); - 0x1: sbb_Ev_Gv(); - 0x2: sbb_Gb_Eb(); - 0x3: sbb_Gv_Ev(); - 0x4: sbb_Al_Ib(); - 0x5: sbb_rAX_Iz(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: push_DS(); } 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: pop_DS(); } + default: MultiInst::SBB(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x04: decode OPCODE_OP_BOTTOM3 { - 0x0: and_Eb_Gb(); - 0x1: and_Ev_Gv(); - 0x2: and_Gb_Eb(); - 0x3: and_Gv_Ev(); - 0x4: and_Al_Ib(); - 0x5: and_rAX_Iz(); 0x6: M5InternalError::error( {{"Tried to execute the ES segment override prefix!"}}); 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: daa(); } + default: MultiInst::AND(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x05: decode OPCODE_OP_BOTTOM3 { - 0x0: sub_Eb_Gb(); - 0x1: sub_Ev_Gv(); - 0x2: sub_Gb_Eb(); - 0x3: sub_Gv_Ev(); - 0x4: sub_Al_Ib(); - 0x5: sub_rAX_Iz(); 0x6: M5InternalError::error( {{"Tried to execute the CS segment override prefix!"}}); 0x7: das(); + default: MultiInst::SUB(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x06: decode OPCODE_OP_BOTTOM3 { - 0x4: Inst::XOR(rAl,Ib); - 0x5: Inst::XOR(rAx,Iz); 0x6: M5InternalError::error( {{"Tried to execute the SS segment override prefix!"}}); 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: aaa(); } default: MultiInst::XOR(OPCODE_OP_BOTTOM3, [Eb,Gb], [Ev,Gv], - [Gb,Eb], [Gv,Ev]); + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x07: decode OPCODE_OP_BOTTOM3 { - 0x0: cmp_Eb_Gb(); - 0x1: cmp_Ev_Gv(); - 0x2: cmp_Gb_Eb(); - 0x3: cmp_Gv_Ev(); - 0x4: cmp_Al_Ib(); - 0x5: cmp_rAX_Iz(); 0x6: M5InternalError::error( {{"Tried to execute the DS segment override prefix!"}}); 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: aas(); } + default: MultiInst::CMP(OPCODE_OP_BOTTOM3, + [Eb,Gb], [Ev,Gv], + [Gb,Eb], [Gv,Ev], + [rAl,Ib], [rAx,Iz]); } 0x08: decode MODE_SUBMODE { 0x0: M5InternalError::error ( {{"Tried to execute an REX prefix!"}}); - default: decode OPCODE_OP_BOTTOM3 { - 0x0: inc_eAX(); - 0x1: inc_eCX(); - 0x2: inc_eDX(); - 0x3: inc_eBX(); - 0x4: inc_eSP(); - 0x5: inc_eBP(); - 0x6: inc_eSI(); - 0x7: inc_eDI(); - } + default: Inst::INC(B); } 0x09: decode MODE_SUBMODE { 0x0: M5InternalError::error ( {{"Tried to execute an REX prefix!"}}); - default: decode OPCODE_OP_BOTTOM3 { - 0x0: dec_eAX(); - 0x1: dec_eCX(); - 0x2: dec_eDX(); - 0x3: dec_eBX(); - 0x4: dec_eSP(); - 0x5: dec_eBP(); - 0x6: dec_eSI(); - 0x7: dec_eDI(); - } + default: Inst::DEC(B); } format Inst { - 0x0A: decode OPCODE_OP_BOTTOM3 { - 0x0: PUSH(rAx); - 0x1: PUSH(rCx); - 0x2: PUSH(rDx); - 0x3: PUSH(rBx); - 0x4: PUSH(rSP); - 0x5: PUSH(rBP); - 0x6: PUSH(rSI); - 0x7: PUSH(rDI); - } - 0x0B: decode OPCODE_OP_BOTTOM3 { - 0x0: POP(rAx); - 0x1: POP(rCx); - 0x2: POP(rDx); - 0x3: POP(rBx); - 0x4: POP(rSP); - 0x5: POP(rBP); - 0x6: POP(rSI); - 0x7: POP(rDI); - } + 0x0A: PUSH(B); + 0x0B: POP(B); } 0x0C: decode OPCODE_OP_BOTTOM3 { 0x0: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: pusha(); } 0x1: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: popa(); } 0x2: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: bound_Gv_Ma(); } 0x3: decode MODE_SUBMODE { @@ -258,58 +210,82 @@ 0x6: outs_Dx_Xb(); 0x7: outs_Dx_Xz(); } - 0x0E: decode OPCODE_OP_BOTTOM3 { - 0x0: jo_Jb(); - 0x1: jno_Jb(); - 0x2: jb_Jb(); - 0x3: jnb_Jb(); - 0x4: jz_Jb(); - 0x5: jnz_Jb(); - 0x6: jbe_Jb(); - 0x7: jnbe_Jb(); - } - 0x0F: decode OPCODE_OP_BOTTOM3 { - 0x0: js_Jb(); - 0x1: jns_Jb(); - 0x2: jp_Jb(); - 0x3: jnp_Jb(); - 0x4: jl_Jb(); - 0x5: jnl_Jb(); - 0x6: jle_Jb(); - 0x7: jnke_Jb(); - } - 0x10: decode OPCODE_OP_BOTTOM3 { - 0x0: group1_Eb_Ib(); - //0x1: group1_Ev_Iz(); - 0x1: decode MODRM_REG { - 0x0: add_Ev_Iz(); - 0x1: or_Ev_Ibz(); - 0x2: adc_Ev_Iz(); - 0x3: sbb_Ev_Iz(); - 0x4: Inst::AND(Ev,Iz); - 0x5: Inst::SUB(Ev,Iz); - 0x6: xor_Ev_Iz(); - 0x7: cmp_Ev_Iz(); - } - 0x2: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: group1_Eb_Ib(); + format Inst { + 0x0E: decode OPCODE_OP_BOTTOM3 { + 0x0: JO(Jb); + 0x1: JNO(Jb); + 0x2: JB(Jb); + 0x3: JNB(Jb); + 0x4: JZ(Jb); + 0x5: JNZ(Jb); + 0x6: JBE(Jb); + 0x7: JNBE(Jb); + } + 0x0F: decode OPCODE_OP_BOTTOM3 { + 0x0: JS(Jb); + 0x1: JNS(Jb); + 0x2: JP(Jb); + 0x3: JNP(Jb); + 0x4: JL(Jb); + 0x5: JNL(Jb); + 0x6: JLE(Jb); + 0x7: JNLE(Jb); } - //0x3: group1_Ev_Ib(); - 0x3: decode MODRM_REG { - 0x0: add_Eb_Ib(); - 0x1: or_Eb_Ib(); - 0x2: adc_Eb_Ib(); - 0x3: sbb_Eb_Ib(); - 0x4: Inst::AND(Eb,Ib); - 0x5: sub_Eb_Ib(); - 0x6: xor_Eb_Ib(); - 0x7: cmp_Eb_Ib(); + } + format Inst { + 0x10: decode OPCODE_OP_BOTTOM3 { + //0x0: group1_Eb_Ib(); + 0x0: decode MODRM_REG { + 0x0: ADD(Eb,Ib); + 0x1: OR(Eb,Ib); + 0x2: ADC(Eb,Ib); + 0x3: SBB(Eb,Ib); + 0x4: AND(Eb,Ib); + 0x5: SUB(Eb,Ib); + 0x6: XOR(Eb,Ib); + 0x7: CMP(Eb,Ib); + } + //0x1: group1_Ev_Iz(); + 0x1: decode MODRM_REG { + 0x0: ADD(Ev,Iz); + 0x1: OR(Ev,Iz); + 0x2: ADC(Ev,Iz); + 0x3: SBB(Ev,Iz); + 0x4: AND(Ev,Iz); + 0x5: SUB(Ev,Iz); + 0x6: XOR(Ev,Iz); + 0x7: CMP(Ev,Iz); + } + 0x2: decode MODE_SUBMODE { + 0x0: UD2(); + //default: group1_Eb_Ib(); + default: decode MODRM_REG { + 0x0: ADD(Eb,Ib); + 0x1: OR(Eb,Ib); + 0x2: ADC(Eb,Ib); + 0x3: SBB(Eb,Ib); + 0x4: AND(Eb,Ib); + 0x5: SUB(Eb,Ib); + 0x6: XOR(Eb,Ib); + 0x7: CMP(Eb,Ib); + } + } + //0x3: group1_Ev_Ib(); + 0x3: decode MODRM_REG { + 0x0: ADD(Ev,Ib); + 0x1: OR(Ev,Ib); + 0x2: ADC(Ev,Ib); + 0x3: SBB(Ev,Ib); + 0x4: AND(Ev,Ib); + 0x5: SUB(Ev,Ib); + 0x6: XOR(Ev,Ib); + 0x7: CMP(Ev,Ib); + } + 0x4: TEST(Eb,Gb); + 0x5: TEST(Ev,Gv); + 0x6: XCHG(Eb,Gb); + 0x7: XCHG(Ev,Gv); } - 0x4: Inst::TEST(Eb,Gb); - 0x5: Inst::TEST(Ev,Gv); - 0x6: xchg_Eb_Gb(); - 0x7: xchg_Ev_Gv(); } 0x11: decode OPCODE_OP_BOTTOM3 { 0x0: Inst::MOV(Eb,Gb); @@ -322,21 +298,15 @@ 0x7: group10_Ev(); //Make sure this is Ev } 0x12: decode OPCODE_OP_BOTTOM3 { - default: nop_or_pause(); //Check for repe prefix - 0x1: xchg_rCX_rAX(); - 0x2: xchg_rDX_rAX(); - 0x3: xchg_rVX_rAX(); - 0x4: xchg_rSP_rAX(); - 0x5: xchg_rBP_rAX(); - 0x6: xchg_rSI_rAX(); - 0x7: xchg_rDI_rAX(); + 0x0: Inst::NOP(); //XXX repe makes this a "pause" + default: xchg_B_rAX(); } 0x13: decode OPCODE_OP_BOTTOM3 { 0x0: cbw_or_cwde_or_cdqe_rAX(); 0x1: cwd_or_cdq_or_cqo_rAX_rDX(); 0x2: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: call_Ap(); + 0x0: Inst::UD2(); + default: call_far_Ap(); } 0x3: fwait(); //aka wait 0x4: pushf_Fv(); @@ -344,11 +314,11 @@ //Both of these should be illegal only if CPUID.AHF64=0, //according to sandpile.org 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: sahf(); } 0x7: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: lahf(); } } @@ -372,48 +342,52 @@ 0x6: scas_Yb_Al(); 0x7: scas_Yv_rAX(); } - 0x16: decode OPCODE_OP_BOTTOM3 { - 0x0: mov_Al_Ib(); - 0x1: mov_Cl_Ib(); - 0x2: mov_Dl_Ib(); - 0x3: mov_Bl_Ib(); - 0x4: mov_Ah_Ib(); - 0x5: mov_Ch_Ib(); - 0x6: mov_Dh_Ib(); - 0x7: mov_Bh_Ib(); - } format Inst { - 0x17: decode OPCODE_OP_BOTTOM3 { - 0x0: MOV(rAX,Iv); - 0x1: MOV(rCX,Iv); - 0x2: MOV(rDX,Iv); - 0x3: MOV(rBX,Iv); - 0x4: MOV(rSP,Iv); - 0x5: MOV(rBP,Iv); - 0x6: MOV(rSI,Iv); - 0x7: MOV(rDI,Iv); - } - } - 0x18: decode OPCODE_OP_BOTTOM3 { - 0x0: group2_Eb_Ib(); - 0x1: group2_Ev_Ib(); - 0x2: ret_near_Iw(); - 0x3: ret_near(); - 0x4: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: les_Gz_Mp(); - } - 0x5: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: lds_Gz_Mp(); - } - //0x6: group12_Eb_Ib(); - 0x6: decode MODRM_REG { - 0x0: Inst::MOV(Eb,Ib); - } - //0x7: group12_Ev_Iz(); - 0x7: decode MODRM_REG { - 0x0: Inst::MOV(Ev,Iz); + 0x16: MOV(B,Ib); + 0x17: MOV(B,Iv); + 0x18: decode OPCODE_OP_BOTTOM3 { + //0x0: group2_Eb_Ib(); + 0x0: decode MODRM_REG { + 0x0: ROL(Eb,Ib); + 0x1: ROR(Eb,Ib); + 0x2: RCL(Eb,Ib); + 0x3: RCR(Eb,Ib); + 0x4: SAL(Eb,Ib); + 0x5: SHR(Eb,Ib); + 0x6: SAL(Eb,Ib); + 0x7: SAR(Eb,Ib); + } + //0x1: group2_Ev_Ib(); + 0x1: decode MODRM_REG { + 0x0: ROL(Ev,Ib); + 0x1: ROR(Ev,Ib); + 0x2: RCL(Ev,Ib); + 0x3: RCR(Ev,Ib); + 0x4: SAL(Ev,Ib); + 0x5: SHR(Ev,Ib); + 0x6: SAL(Ev,Ib); + 0x7: SAR(Ev,Ib); + } + 0x2: RET_NEAR(Iw); + 0x3: RET_NEAR(); + 0x4: decode MODE_SUBMODE { + 0x0: UD2(); + default: WarnUnimpl::les_Gz_Mp(); + } + 0x5: decode MODE_SUBMODE { + 0x0: UD2(); + default: WarnUnimpl::lds_Gz_Mp(); + } + //0x6: group12_Eb_Ib(); + 0x6: decode MODRM_REG { + 0x0: MOV(Eb,Ib); + default: UD2(); + } + //0x7: group12_Ev_Iz(); + 0x7: decode MODRM_REG { + 0x0: MOV(Ev,Iz); + default: UD2(); + } } } 0x19: decode OPCODE_OP_BOTTOM3 { @@ -424,7 +398,7 @@ 0x4: int3(); 0x5: int_Ib(); 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: into(); } 0x7: iret(); @@ -435,15 +409,15 @@ 0x2: group2_Eb_Cl(); 0x3: group2_Ev_Cl(); 0x4: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: aam_Ib(); } 0x5: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: aad_Ib(); } 0x6: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); + 0x0: Inst::UD2(); default: salc(); } 0x7: xlat(); @@ -469,13 +443,13 @@ 0x7: out_Ib_eAX(); } 0x1D: decode OPCODE_OP_BOTTOM3 { - 0x0: Inst::CALL(Jz); - 0x1: jmp_Jz(); + 0x0: Inst::CALL_NEAR(Jz); + 0x1: Inst::JMP(Jz); 0x2: decode MODE_SUBMODE { - 0x0: This_should_be_an_illegal_instruction(); - default: jmp_Ap(); + 0x0: Inst::UD2(); + default: jmp_far_Ap(); } - 0x3: jmp_Jb(); + 0x3: Inst::JMP(Jb); 0x4: in_Al_Dx(); 0x5: in_eAX_Dx(); 0x6: out_Dx_Al(); @@ -501,8 +475,25 @@ 0x3: sti(); 0x4: cld(); 0x5: std(); - 0x6: group4(); - 0x7: group5(); + format Inst { + //0x6: group4(); + 0x6: decode MODRM_REG { + 0x0: INC(Eb); + 0x1: DEC(Eb); + default: UD2(); + } + //0x7: group5(); + 0x7: decode MODRM_REG { + 0x0: INC(Ev); + 0x1: DEC(Ev); + 0x2: CALL_NEAR(Ev); + 0x3: WarnUnimpl::call_far_Mp(); + 0x4: JMP(Ev); + 0x5: WarnUnimpl::jmp_far_Mp(); + 0x6: PUSH(Ev); + 0x7: UD2(); + } + } } } default: FailUnimpl::oneByteOps(); diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index f05c33bdb..e5631d37b 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -58,7 +58,7 @@ // Decode the two byte opcodes // 0x2: decode OPCODE_PREFIXA { - 0xF0: decode OPCODE_OP_TOP5 { + 0x0F: decode OPCODE_OP_TOP5 { format WarnUnimpl { 0x00: decode OPCODE_OP_BOTTOM3 { 0x00: group6(); @@ -67,23 +67,25 @@ 0x03: lsl_Gv_Ew(); //sandpile.org doesn't seem to know what this is... ? 0x04: loadall_or_reset_or_hang(); - //sandpile.org says (AMD) after syscall, so I might want to check - //if that means amd64 or AMD machines - 0x05: loadall_or_syscall(); +#if FULL_SYSTEM + 0x05: syscall(); +#else + 0x05: SyscallInst::syscall('xc->syscall(rax)'); +#endif 0x06: clts(); //sandpile.org says (AMD) after sysret, so I might want to check //if that means amd64 or AMD machines 0x07: loadall_or_sysret(); } 0x01: decode OPCODE_OP_BOTTOM3 { - 0x0: holderholder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: invd(); + 0x1: wbinvd(); + 0x2: Inst::UD2(); + 0x3: UD2(); + 0x4: Inst::UD2(); + 0x5: threednow(); + 0x6: threednow(); + 0x7: threednow(); } 0x02: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); @@ -96,14 +98,14 @@ 0x7: holder(); } 0x03: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: group17(); + 0x1: group17(); + 0x2: group17(); + 0x3: group17(); + 0x4: group17(); + 0x5: group17(); + 0x6: group17(); + 0x7: group17(); } 0x04: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); @@ -126,44 +128,44 @@ 0x7: holder(); } 0x06: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: wrmsr(); + 0x1: rdtsc(); + 0x2: rdmsr(); + 0x3: rdpmc(); + 0x4: sysenter(); + 0x5: sysexit(); + 0x6: Inst::UD2(); + 0x7: getsec(); } 0x07: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: three_byte_opcode(); + 0x1: three_byte_opcode(); + 0x2: three_byte_opcode(); + 0x3: three_byte_opcode(); + 0x4: three_byte_opcode(); + 0x5: three_byte_opcode(); + 0x6: three_byte_opcode(); + 0x7: three_byte_opcode(); } 0x08: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: cmovo_Gv_Ev(); + 0x1: cmovno_Gv_Ev(); + 0x2: cmovb_Gv_Ev(); + 0x3: cmovnb_Gv_Ev(); + 0x4: cmovz_Gv_Ev(); + 0x5: cmovnz_Gv_Ev(); + 0x6: cmovbe_Gv_Ev(); + 0x7: cmovnbe_Gv_Ev(); } 0x09: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: cmovs_Gv_Ev(); + 0x1: cmovns_Gv_Ev(); + 0x2: cmovp_Gv_Ev(); + 0x3: cmovnp_Gv_Ev(); + 0x4: cmovl_Gv_Ev(); + 0x5: cmovnl_Gv_Ev(); + 0x6: cmovle_Gv_Ev(); + 0x7: cmovnle_Gv_Ev(); } 0x0A: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); @@ -225,85 +227,87 @@ 0x6: holder(); 0x7: holder(); } - 0x10: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); - } - 0x11: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + format Inst { + 0x10: decode OPCODE_OP_BOTTOM3 { + 0x0: JO(Jz); + 0x1: JNO(Jz); + 0x2: JB(Jz); + 0x3: JNB(Jz); + 0x4: JZ(Jz); + 0x5: JNZ(Jz); + 0x6: JBE(Jz); + 0x7: JNBE(Jz); + } + 0x11: decode OPCODE_OP_BOTTOM3 { + 0x0: JS(Jz); + 0x1: JNS(Jz); + 0x2: JP(Jz); + 0x3: JNP(Jz); + 0x4: JL(Jz); + 0x5: JNL(Jz); + 0x6: JLE(Jz); + 0x7: JNLE(Jz); + } } 0x12: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: seto_Eb(); + 0x1: setno_Eb(); + 0x2: setb_Eb(); + 0x3: setnb_Eb(); + 0x4: setz_Eb(); + 0x5: setnz_Eb(); + 0x6: setbe_Eb(); + 0x7: setnbe_Eb(); } 0x13: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: sets_Eb(); + 0x1: setns_Eb(); + 0x2: setp_Eb(); + 0x3: setnp_Eb(); + 0x4: setl_Eb(); + 0x5: setnl_Eb(); + 0x6: setle_Eb(); + 0x7: setnle_Eb(); } 0x14: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: push_fs(); + 0x1: pop_fs(); + 0x2: cpuid(); + 0x3: bt_Ev_Gv(); + 0x4: shld_Ev_Gv_Ib(); + 0x5: shld_Ev_Gv_rCl(); + 0x6: xbts_and_cmpxchg(); + 0x7: ibts_and_cmpxchg(); } 0x15: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: push_gs(); + 0x1: pop_gs(); + 0x2: rsm_smm(); + 0x3: bts_Ev_Gv(); + 0x4: shrd_Ev_Gv_Ib(); + 0x5: shrd_Ev_Gv_rCl(); + 0x6: group16(); + 0x7: Inst::IMUL(Gv,Ev); } 0x16: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: cmpxchg_Eb_Gb(); + 0x1: cmpxchg_Ev_Gv(); + 0x2: lss_Gz_Mp(); + 0x3: btr_Ev_Gv(); + 0x4: lfs_Gz_Mp(); + 0x5: lgs_Gz_Mp(); + 0x6: Inst::MOVZX_B(Gv,Eb); + 0x7: Inst::MOVZX_W(Gv,Ew); } 0x17: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); + 0x0: jmpe_Jz(); // IA-64? + 0x1: group11_UD2(); + 0x2: group8_Ev_Ib(); + 0x3: btc_Ev_Gv(); + 0x4: bsf_Gv_Ev(); + 0x5: bsr_Gv_Ev(); + 0x6: Inst::MOVSX_B(Gv,Eb); + 0x7: Inst::MOVSX_W(Gv,Ew); } 0x18: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); @@ -315,16 +319,7 @@ 0x6: holder(); 0x7: holder(); } - 0x19: decode OPCODE_OP_BOTTOM3 { - 0x0: holder(); - 0x1: holder(); - 0x2: holder(); - 0x3: holder(); - 0x4: holder(); - 0x5: holder(); - 0x6: holder(); - 0x7: holder(); - } + 0x19: bswap_B(); 0x1A: decode OPCODE_OP_BOTTOM3 { 0x0: holder(); 0x1: holder(); diff --git a/src/arch/x86/isa/formats/error.isa b/src/arch/x86/isa/formats/error.isa index 8ac2ea44d..e85eff762 100644 --- a/src/arch/x86/isa/formats/error.isa +++ b/src/arch/x86/isa/formats/error.isa @@ -64,7 +64,7 @@ def template ErrorDecode {{ { - panic("X86 decoder internal error: '%%s' %%s", + panic("X86 decoder internal error: '%s' %s", %(message)s, machInst); } }}; diff --git a/src/arch/x86/isa/formats/formats.isa b/src/arch/x86/isa/formats/formats.isa index d763c05bc..1e7bb4a74 100644 --- a/src/arch/x86/isa/formats/formats.isa +++ b/src/arch/x86/isa/formats/formats.isa @@ -98,3 +98,7 @@ //Include a format which implements a batch of instructions which do the same //thing on a variety of inputs ##include "multi.isa" + +//Include a format which makes instructions who's sole purpose is to generate +//a syscall. +##include "syscall.isa" diff --git a/src/arch/x86/isa/formats/syscall.isa b/src/arch/x86/isa/formats/syscall.isa new file mode 100644 index 000000000..8b860dba4 --- /dev/null +++ b/src/arch/x86/isa/formats/syscall.isa @@ -0,0 +1,112 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// 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 + +//////////////////////////////////////////////////////////////////// +// +// "Format" which describes an instruction whose only purpose is to +// call a syscall in SE mode. +// + +output header {{ + class SyscallInst : public X86ISA::X86StaticInst + { + public: + /// Constructor + SyscallInst(const char *_mnemonic, ExtMachInst _machInst, + OpClass __opClass) : + X86ISA::X86StaticInst(_mnemonic, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string SyscallInst::generateDisassembly(Addr PC, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + ccprintf(response, " "); + printReg(response, _srcRegIdx[0], machInst.opSize); + return response.str(); + } +}}; + +def template SyscallExecute {{ + 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; + return fault; + } +}}; + +def format SyscallInst(code, *opt_flags) {{ + iop = InstObjParams(name, Name, 'SyscallInst', code, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = SyscallExecute.subst(iop) +}}; + diff --git a/src/arch/x86/isa/formats/unimp.isa b/src/arch/x86/isa/formats/unimp.isa index 12fa8387b..183beb3b8 100644 --- a/src/arch/x86/isa/formats/unimp.isa +++ b/src/arch/x86/isa/formats/unimp.isa @@ -68,12 +68,12 @@ output header {{ * 'Unknown' class is used for unrecognized/illegal instructions. * This is a leaf class. */ - class FailUnimplemented : public X86StaticInst + class FailUnimplemented : public X86ISA::X86StaticInst { public: /// Constructor FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst) - : X86StaticInst(_mnemonic, _machInst, No_OpClass) + : X86ISA::X86StaticInst(_mnemonic, _machInst, No_OpClass) { // don't call execute() (which panics) if we're on a // speculative path @@ -95,7 +95,7 @@ output header {{ * probably make the 'warned' flag a static member of the derived * class. */ - class WarnUnimplemented : public X86StaticInst + class WarnUnimplemented : public X86ISA::X86StaticInst { private: /// Have we warned on this instruction yet? @@ -104,7 +104,7 @@ output header {{ public: /// Constructor WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst) - : X86StaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + : X86ISA::X86StaticInst(_mnemonic, _machInst, No_OpClass), warned(false) { // don't call execute() (which panics) if we're on a // speculative path diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa index 4f27c72f5..58aef7b1d 100644 --- a/src/arch/x86/isa/includes.isa +++ b/src/arch/x86/isa/includes.isa @@ -97,6 +97,9 @@ output header {{ #include <iostream> #include "arch/x86/emulenv.hh" +#include "arch/x86/insts/microldstop.hh" +#include "arch/x86/insts/microregop.hh" +#include "arch/x86/insts/static_inst.hh" #include "arch/x86/isa_traits.hh" #include "arch/x86/regfile.hh" #include "arch/x86/types.hh" @@ -108,6 +111,7 @@ output header {{ output decoder {{ #include "arch/x86/faults.hh" +#include "arch/x86/miscregs.hh" #include "arch/x86/segmentregs.hh" #include "base/cprintf.hh" #include "base/loader/symtab.hh" diff --git a/src/arch/x86/isa/insts/__init__.py b/src/arch/x86/isa/insts/__init__.py index 717690926..f5c4e3113 100644 --- a/src/arch/x86/isa/insts/__init__.py +++ b/src/arch/x86/isa/insts/__init__.py @@ -69,7 +69,8 @@ categories = ["arithmetic", "rotate_and_shift", "semaphores", "string", - "system_calls"] + "system_calls", + "system"] microcode = ''' # X86 microcode diff --git a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py index 809b9ac7c..05aa6cd69 100644 --- a/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py +++ b/src/arch/x86/isa/insts/arithmetic/add_and_subtract.py @@ -54,23 +54,227 @@ # Authors: Gabe Black microcode = ''' +def macroop ADD_R_R +{ + add reg, reg, regm +}; + +def macroop ADD_R_I +{ + limm t1, imm + add reg, reg, t1 +}; + +def macroop ADD_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + add t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop ADD_P_I +{ + rdip t7 + limm t2, imm + ld t1, ds, [scale, index, base], disp + add t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop ADD_M_R +{ + ld t1, ds, [scale, index, base], disp + add t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADD_P_R +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + add t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADD_R_M +{ + ld t1, ds, [scale, index, base], disp + add reg, reg, t1 +}; + +def macroop ADD_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + add reg, reg, t1 +}; + +def macroop SUB_R_R +{ + sub reg, reg, regm +}; + def macroop SUB_R_I { - subi reg, reg, imm + limm t1, imm + sub reg, reg, t1 +}; + +def macroop SUB_R_M +{ + ld t1, ds, [scale, index, base], disp + sub reg, reg, t1 +}; + +def macroop SUB_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + sub reg, reg, t1 }; def macroop SUB_M_I { + limm t2, imm ld t1, ds, [scale, index, base], disp - subi t1, t1, imm + sub t1, t1, t2 st t1, ds, [scale, index, base], disp }; def macroop SUB_P_I { rdip t7 + limm t2, imm + ld t1, ds, [scale, index, base], disp + sub t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop SUB_M_R +{ + ld t1, ds, [scale, index, base], disp + sub t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop SUB_P_R +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + sub t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_R_R +{ + adc reg, reg, regm +}; + +def macroop ADC_R_I +{ + limm t1, imm + adc reg, reg, t1 +}; + +def macroop ADC_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + adc t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_P_I +{ + rdip t7 + limm t2, imm + ld t1, ds, [scale, index, base], disp + adc t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_M_R +{ + ld t1, ds, [scale, index, base], disp + adc t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_P_R +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + adc t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop ADC_R_M +{ + ld t1, ds, [scale, index, base], disp + adc reg, reg, t1 +}; + +def macroop ADC_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + adc reg, reg, t1 +}; + +def macroop SBB_R_R +{ + sbb reg, reg, regm +}; + +def macroop SBB_R_I +{ + limm t1, imm + sbb reg, reg, t1 +}; + +def macroop SBB_R_M +{ + ld t1, ds, [scale, index, base], disp + sbb reg, reg, t1 +}; + +def macroop SBB_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + sbb reg, reg, t1 +}; + +def macroop SBB_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + sbb t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop SBB_P_I +{ + rdip t7 + limm t2, imm + ld t1, ds, [scale, index, base], disp + sbb t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop SBB_M_R +{ + ld t1, ds, [scale, index, base], disp + sbb t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop SBB_P_R +{ + rdip t7 ld t1, ds, [scale, index, base], disp - subi t1, t1, imm + sbb t1, t1, reg st t1, ds, [scale, index, base], disp }; ''' diff --git a/src/arch/x86/isa/insts/arithmetic/increment_and_decrement.py b/src/arch/x86/isa/insts/arithmetic/increment_and_decrement.py index c504d47ce..eed39c10c 100644 --- a/src/arch/x86/isa/insts/arithmetic/increment_and_decrement.py +++ b/src/arch/x86/isa/insts/arithmetic/increment_and_decrement.py @@ -53,7 +53,47 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop INC_R +{ + addi reg, reg, 1, flags=(OF, SF, ZF, AF, PF) +}; + +def macroop INC_M +{ + ld t1, ds, [scale, index, base], disp + addi t1, t1, 1, flags=(OF, SF, ZF, AF, PF) + st t1, ds, [scale, index, base], disp +}; + +def macroop INC_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + addi reg, reg, 1, flags=(OF, SF, ZF, AF, PF) + st t1, ds, [0, t0, t7], disp +}; + +def macroop DEC_R +{ + subi reg, reg, 1, flags=(OF, SF, ZF, AF, PF) +}; + +def macroop DEC_M +{ + ld t1, ds, [scale, index, base], disp + subi t1, t1, 1, flags=(OF, SF, ZF, AF, PF) + st t1, ds, [scale, index, base], disp +}; + +def macroop DEC_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + subi reg, reg, 1, flags=(OF, SF, ZF, AF, PF) + st t1, ds, [0, t0, t7], disp +}; +''' #let {{ # class DEC(Inst): # "GenFault ${new UnimpInstFault}" diff --git a/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py b/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py index 662022e6a..8697bef65 100644 --- a/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py +++ b/src/arch/x86/isa/insts/arithmetic/multiply_and_divide.py @@ -53,7 +53,31 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' + +# +# Two operand signed multiply. These should set the CF and OF flags if the +# result is too large for the destination register +# + +def macroop IMUL_R_R +{ + mul1s reg, reg, regm +}; + +def macroop IMUL_R_M +{ + ld t1, ds, [scale, index, base], disp + mul1s reg, reg, t1 +}; + +def macroop IMUL_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + mul1s reg, reg, t1 +}; +''' #let {{ # class MUL(Inst): # "GenFault ${new UnimpInstFault}" diff --git a/src/arch/x86/isa/insts/compare_and_test/compare.py b/src/arch/x86/isa/insts/compare_and_test/compare.py index 12b5b859f..8f5890b23 100644 --- a/src/arch/x86/isa/insts/compare_and_test/compare.py +++ b/src/arch/x86/isa/insts/compare_and_test/compare.py @@ -53,8 +53,56 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class CMP(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop CMP_R_M +{ + ld t1, ds, [scale, index, base], disp + sub t0, reg, t1, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_R_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + sub t0, reg, t1, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_P_I +{ + limm t2, imm + rdip t7 + ld t1, ds, [0, t0, t7], disp + sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_M_R +{ + ld t1, ds, [scale, index, base], disp + sub t0, t1, reg, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_P_R +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + sub t0, t1, reg, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_R_R +{ + sub t0, reg, regm, flags=(OF, SF, ZF, AF, PF, CF) +}; + +def macroop CMP_R_I +{ + limm t1, imm + sub t0, reg, t1, flags=(OF, SF, ZF, AF, PF, CF) +}; +''' diff --git a/src/arch/x86/isa/insts/compare_and_test/test.py b/src/arch/x86/isa/insts/compare_and_test/test.py index 89d406912..8da33899a 100644 --- a/src/arch/x86/isa/insts/compare_and_test/test.py +++ b/src/arch/x86/isa/insts/compare_and_test/test.py @@ -57,39 +57,39 @@ microcode = ''' def macroop TEST_M_R { ld t1, ds, [scale, index, base], disp - and t0, t1, reg + and t0, t1, reg, flags=(SF, ZF, PF) }; def macroop TEST_P_R { rdip t7 - ld t1, ds, [scale, index, base], disp - and t0, t1, reg + ld t1, ds, [0, t0, t7], disp + and t0, t1, reg, flags=(SF, ZF, PF) }; def macroop TEST_R_R { - and t0, reg, regm + and t0, reg, regm, flags=(SF, ZF, PF) }; def macroop TEST_M_I { ld t1, ds, [scale, index, base], disp limm t2, imm - and t0, t1, t2 + and t0, t1, t2, flags=(SF, ZF, PF) }; def macroop TEST_P_I { rdip t7 - ld t1, ds, [scale, index, base], disp + ld t1, ds, [0, t0, t7], disp limm t2, imm - and t0, t1, t2 + and t0, t1, t2, flags=(SF, ZF, PF) }; def macroop TEST_R_I { limm t1, imm - and t0, reg, t1 + and t0, reg, t1, flags=(SF, ZF, PF) }; ''' diff --git a/src/arch/x86/isa/insts/control_transfer/call.py b/src/arch/x86/isa/insts/control_transfer/call.py index 530162bfd..c5bb66e58 100644 --- a/src/arch/x86/isa/insts/control_transfer/call.py +++ b/src/arch/x86/isa/insts/control_transfer/call.py @@ -54,16 +54,51 @@ # Authors: Gabe Black microcode = ''' -def macroop CALL_I +def macroop CALL_NEAR_I { - # Make the default data size of pops 64 bits in 64 bit mode + # Make the default data size of calls 64 bits in 64 bit mode + .adjust_env oszIn64Override + + limm t1, imm + rdip t7 + subi rsp, rsp, dsz + st t7, ss, [0, t0, rsp] + wrip t7, t1 +}; + +def macroop CALL_NEAR_R +{ + # Make the default data size of calls 64 bits in 64 bit mode .adjust_env oszIn64Override - limm t2, imm rdip t1 subi rsp, rsp, dsz st t1, ss, [0, t0, rsp] - wrip t1, t2 + wripi reg, 0 +}; + +def macroop CALL_NEAR_M +{ + # Make the default data size of calls 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t7 + ld t1, ds, [scale, index, base], disp + subi rsp, rsp, dsz + st t7, ss, [0, t0, rsp] + wripi t1, 0 +}; + +def macroop CALL_NEAR_P +{ + # Make the default data size of calls 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t7 + ld t1, ds, [0, t0, t7], disp + subi rsp, rsp, dsz + st t7, ss, [0, t0, rsp] + wripi t1, 0 }; ''' #let {{ diff --git a/src/arch/x86/isa/insts/control_transfer/jump.py b/src/arch/x86/isa/insts/control_transfer/jump.py index e90e5b12b..158861a3d 100644 --- a/src/arch/x86/isa/insts/control_transfer/jump.py +++ b/src/arch/x86/isa/insts/control_transfer/jump.py @@ -53,8 +53,192 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class JMP(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop JZ_I +{ + # Make the defualt data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CZF,) +}; + +def macroop JNZ_I +{ + # Make the defualt data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCZF,) +}; + +def macroop JB_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CCF,) +}; + +def macroop JNB_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCCF,) +}; + +def macroop JBE_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CCvZF,) +}; + +def macroop JNBE_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCCvZF,) +}; + +def macroop JS_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CSF,) +}; + +def macroop JNS_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCSF,) +}; + +def macroop JP_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CPF,) +}; + +def macroop JNP_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCPF,) +}; + +def macroop JL_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CSxOF,) +}; + +def macroop JNL_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCSxOF,) +}; + +def macroop JLE_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(CSxOvZF,) +}; + +def macroop JNLE_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCSxOvZF,) +}; + +def macroop JO_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(COF,) +}; + +def macroop JNO_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2, flags=(nCOF,) +}; + +def macroop JMP_I +{ + # Make the default data size of jumps 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t1 + limm t2, imm + wrip t1, t2 +}; + +def macroop JMP_R +{ + wripi reg, 0 +}; + +def macroop JMP_M +{ + ld t1, ds, [scale, index, base], disp + wripi t1, 0 +}; + +def macroop JMP_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + wripi t1, 0 +}; +''' diff --git a/src/arch/x86/isa/insts/control_transfer/xreturn.py b/src/arch/x86/isa/insts/control_transfer/xreturn.py index aaffa2b92..0000cd3c1 100644 --- a/src/arch/x86/isa/insts/control_transfer/xreturn.py +++ b/src/arch/x86/isa/insts/control_transfer/xreturn.py @@ -53,8 +53,26 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class RET(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop RET_NEAR +{ + # Make the default data size of rets 64 bits in 64 bit mode + .adjust_env oszIn64Override + + ld t1, ss, [0, t0, rsp] + addi rsp, rsp, dsz + wripi t1, 0 +}; + +def macroop RET_NEAR_I +{ + # Make the default data size of rets 64 bits in 64 bit mode + .adjust_env oszIn64Override + + limm t2, imm + ld t1, ss, [0, t0, rsp] + addi rsp, rsp, dsz + add rsp, rsp, t2 + wripi t1, 0 +}; +''' diff --git a/src/arch/x86/isa/insts/data_transfer/__init__.py b/src/arch/x86/isa/insts/data_transfer/__init__.py index eda173b34..365f95eaa 100644 --- a/src/arch/x86/isa/insts/data_transfer/__init__.py +++ b/src/arch/x86/isa/insts/data_transfer/__init__.py @@ -55,7 +55,8 @@ categories = ["conditional_move", "move", - "stack_operations"] + "stack_operations", + "xchg"] microcode = "" for category in categories: diff --git a/src/arch/x86/isa/insts/data_transfer/move.py b/src/arch/x86/isa/insts/data_transfer/move.py index c85dd7cc4..bbc55e47c 100644 --- a/src/arch/x86/isa/insts/data_transfer/move.py +++ b/src/arch/x86/isa/insts/data_transfer/move.py @@ -54,6 +54,11 @@ # Authors: Gabe Black microcode = ''' + +# +# Regular moves +# + def macroop MOV_R_R { mov reg, reg, regm }; @@ -64,7 +69,7 @@ def macroop MOV_M_R { def macroop MOV_P_R { rdip t7 - st reg, ds, [scale, index, base], disp + st reg, ds, [0, t0, t7], disp }; def macroop MOV_R_M { @@ -73,7 +78,7 @@ def macroop MOV_R_M { def macroop MOV_R_P { rdip t7 - ld reg, ds, [scale, index, base], disp + ld reg, ds, [0, t0, t7], disp }; def macroop MOV_R_I { @@ -88,22 +93,90 @@ def macroop MOV_M_I { def macroop MOV_P_I { rdip t7 limm t1, imm - st t1, ds, [scale, index, base], disp + st t1, ds, [0, t0, t7], disp }; +# +# Sign extending moves +# + def macroop MOVSXD_R_R { - sext reg, regm, dsz + sext reg, regm, 32 }; def macroop MOVSXD_R_M { - ld t1, ds, [scale, index, base], disp - sext reg, t1, dsz + ld t1, ds, [scale, index, base], disp, dataSize=4 + sext reg, t1, 32 }; def macroop MOVSXD_R_P { rdip t7 - ld t1, ds, [scale, index, base], disp - sext reg, t1, dsz + ld t1, ds, [0, t0, t7], disp, dataSize=4 + sext reg, t1, 32 +}; + +def macroop MOVSX_B_R_R { + sext reg, regm, 8 +}; + +def macroop MOVSX_B_R_M { + ld reg, ds, [scale, index, base], disp, dataSize=1 + sext reg, reg, 8 +}; + +def macroop MOVSX_B_R_P { + rdip t7 + ld reg, ds, [0, t0, t7], disp, dataSize=1 + sext reg, reg, 8 +}; + +def macroop MOVSX_W_R_R { + sext reg, regm, 16 +}; + +def macroop MOVSX_W_R_M { + ld reg, ds, [scale, index, base], disp, dataSize=2 + sext reg, reg, 16 +}; + +def macroop MOVSX_W_R_P { + rdip t7 + ld reg, ds, [0, t0, t7], disp, dataSize=2 + sext reg, reg, 16 +}; + +# +# Zero extending moves +# + +def macroop MOVZX_B_R_R { + zext reg, regm, 8 +}; + +def macroop MOVZX_B_R_M { + ld t1, ds, [scale, index, base], disp, dataSize=1 + zext reg, t1, 8 +}; + +def macroop MOVZX_B_R_P { + rdip t7 + ld t1, ds, [0, t0, t7], disp, dataSize=1 + zext reg, t1, 8 +}; + +def macroop MOVZX_W_R_R { + zext reg, regm, 16 +}; + +def macroop MOVZX_W_R_M { + ld t1, ds, [scale, index, base], disp, dataSize=2 + zext reg, t1, 16 +}; + +def macroop MOVZX_W_R_P { + rdip t7 + ld t1, ds, [0, t0, t7], disp, dataSize=2 + zext reg, t1, 16 }; ''' #let {{ diff --git a/src/arch/x86/isa/insts/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/data_transfer/stack_operations.py index 585437b8c..c381dc4f4 100644 --- a/src/arch/x86/isa/insts/data_transfer/stack_operations.py +++ b/src/arch/x86/isa/insts/data_transfer/stack_operations.py @@ -69,6 +69,25 @@ def macroop PUSH_R { subi rsp, rsp, dsz st reg, ss, [0, t0, rsp] }; + +def macroop PUSH_M { + # Make the default data size of pops 64 bits in 64 bit mode + .adjust_env oszIn64Override + + ld t1, ds, [scale, index, base], disp + subi rsp, rsp, dsz + st t1, ss, [0, t0, rsp] +}; + +def macroop PUSH_P { + # Make the default data size of pops 64 bits in 64 bit mode + .adjust_env oszIn64Override + + rdip t7 + ld t1, ds, [0, t0, t7], disp + subi rsp, rsp, dsz + st t1, ss, [0, t0, rsp] +}; ''' #let {{ # class POPA(Inst): diff --git a/src/arch/x86/isa/insts/data_transfer/xchg.py b/src/arch/x86/isa/insts/data_transfer/xchg.py new file mode 100644 index 000000000..4f401deb7 --- /dev/null +++ b/src/arch/x86/isa/insts/data_transfer/xchg.py @@ -0,0 +1,98 @@ +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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 + +microcode = ''' + +# All the memory versions need to use LOCK, regardless of if it was set + +def macroop XCHG_R_R +{ + # Use the xor trick instead of moves to reduce register pressure. + # This probably doesn't make much of a difference, but it's easy. + xor reg, reg, regm + xor regm, regm, reg + xor reg, reg, regm +}; + +def macroop XCHG_R_M +{ + ld t1, ds, [scale, index, base], disp + st reg, ds, [scale, index, base], disp + mov reg, reg, t1 +}; + +def macroop XCHG_R_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + st reg, ds, [0, t0, t7], disp + mov reg, reg, t1 +}; + +def macroop XCHG_M_R +{ + ld t1, ds, [scale, index, base], disp + st reg, ds, [scale, index, base], disp + mov reg, reg, t1 +}; + +def macroop XCHG_P_R +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + st reg, ds, [0, t0, t7], disp + mov reg, reg, t1 +}; +''' diff --git a/src/arch/x86/isa/insts/logical.py b/src/arch/x86/isa/insts/logical.py index 2fd369d60..f99638cac 100644 --- a/src/arch/x86/isa/insts/logical.py +++ b/src/arch/x86/isa/insts/logical.py @@ -54,6 +54,62 @@ # Authors: Gabe Black microcode = ''' +def macroop OR_R_R +{ + or reg, reg, regm +}; + +def macroop OR_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + or t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop OR_P_I +{ + limm t2, imm + rdip t7 + ld t1, ds, [0, t0, t7], disp + or t1, t1, t2 + st t1, ds, [0, t0, t7], disp +}; + +def macroop OR_M_R +{ + ld t1, ds, [scale, index, base], disp + or t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop OR_P_R +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + or t1, t1, reg + st t1, ds, [0, t0, t7], disp +}; + +def macroop OR_R_M +{ + ld t1, ds, [scale, index, base], disp + or reg, reg, t1 +}; + +def macroop OR_R_P +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + or reg, reg, t1 +}; + +def macroop OR_R_I +{ + limm t1, imm + or reg, reg, t1 +}; + def macroop XOR_R_R { xor reg, reg, regm @@ -65,6 +121,23 @@ def macroop XOR_R_I xor reg, reg, t1 }; +def macroop XOR_M_I +{ + limm t2, imm + ld t1, ds, [scale, index, base], disp + xor t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + +def macroop XOR_P_I +{ + limm t2, imm + rdip t7 + ld t1, ds, [scale, index, base], disp + xor t1, t1, t2 + st t1, ds, [scale, index, base], disp +}; + def macroop XOR_M_R { ld t1, ds, [scale, index, base], disp @@ -93,6 +166,24 @@ def macroop XOR_R_P xor reg, reg, t1 }; +def macroop AND_R_R +{ + and reg, reg, regm +}; + +def macroop AND_R_M +{ + ld t1, ds, [scale, index, base], disp + and reg, reg, t1 +}; + +def macroop AND_R_P +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + and reg, reg, t1 +}; + def macroop AND_R_I { limm t1, imm @@ -115,6 +206,21 @@ def macroop AND_P_I and t2, t2, t1 st t2, ds, [scale, index, base], disp }; + +def macroop AND_M_R +{ + ld t1, ds, [scale, index, base], disp + and t1, t1, reg + st t1, ds, [scale, index, base], disp +}; + +def macroop AND_P_R +{ + rdip t7 + ld t1, ds, [scale, index, base], disp + and t1, t1, reg + st t1, ds, [scale, index, base], disp +}; ''' #let {{ #microcodeString = ''' diff --git a/src/arch/x86/isa/insts/no_operation.py b/src/arch/x86/isa/insts/no_operation.py index 1a287aea7..306ee2797 100644 --- a/src/arch/x86/isa/insts/no_operation.py +++ b/src/arch/x86/isa/insts/no_operation.py @@ -53,8 +53,9 @@ # # Authors: Gabe Black -microcode = "" -#let {{ -# class NOP(Inst): -# "GenFault ${new UnimpInstFault}" -#}}; +microcode = ''' +def macroop NOP +{ + fault "NoFault" +}; +''' diff --git a/src/arch/x86/isa/insts/rotate_and_shift/rotate.py b/src/arch/x86/isa/insts/rotate_and_shift/rotate.py index e3aaf0043..0988f8815 100644 --- a/src/arch/x86/isa/insts/rotate_and_shift/rotate.py +++ b/src/arch/x86/isa/insts/rotate_and_shift/rotate.py @@ -53,14 +53,90 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop ROL_R_I +{ + rol reg, reg, imm +}; + +def macroop ROL_M_I +{ + ld t1, ds, [scale, index, base], disp + rol t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop ROL_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + rol t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; + +def macroop ROR_R_I +{ + ror reg, reg, imm +}; + +def macroop ROR_M_I +{ + ld t1, ds, [scale, index, base], disp + ror t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop ROR_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + ror t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; + +def macroop RCL_R_I +{ + rcl reg, reg, imm +}; + +def macroop RCL_M_I +{ + ld t1, ds, [scale, index, base], disp + rcl t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop RCL_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + rcl t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; + +def macroop RCR_R_I +{ + rcr reg, reg, imm +}; + +def macroop RCR_M_I +{ + ld t1, ds, [scale, index, base], disp + rcr t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop RCR_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + rcr t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; +''' #let {{ # class RCL(Inst): # "GenFault ${new UnimpInstFault}" # class RCR(Inst): # "GenFault ${new UnimpInstFault}" -# class ROL(Inst): -# "GenFault ${new UnimpInstFault}" -# class ROR(Inst): -# "GenFault ${new UnimpInstFault}" #}}; diff --git a/src/arch/x86/isa/insts/rotate_and_shift/shift.py b/src/arch/x86/isa/insts/rotate_and_shift/shift.py index f72794657..5a04317d9 100644 --- a/src/arch/x86/isa/insts/rotate_and_shift/shift.py +++ b/src/arch/x86/isa/insts/rotate_and_shift/shift.py @@ -53,7 +53,67 @@ # # Authors: Gabe Black -microcode = "" +microcode = ''' +def macroop SAL_R_I +{ + sll reg, reg, imm +}; + +def macroop SAL_M_I +{ + ld t1, ds, [scale, index, base], disp + sll t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop SAL_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + sll t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; + +def macroop SHR_R_I +{ + srl reg, reg, imm +}; + +def macroop SHR_M_I +{ + ld t1, ds, [scale, index, base], disp + srl t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop SHR_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + srl t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; + +def macroop SAR_R_I +{ + sra reg, reg, imm +}; + +def macroop SAR_M_I +{ + ld t1, ds, [scale, index, base], disp + sra t1, t1, imm + st t1, ds, [scale, index, base], disp +}; + +def macroop SAR_P_I +{ + rdip t7 + ld t1, ds, [0, t0, t7], disp + sra t1, t1, imm + st t1, ds, [0, t0, t7], disp +}; +''' #let {{ # class SAL(Inst): # "GenFault ${new UnimpInstFault}" diff --git a/src/arch/x86/isa/insts/system/__init__.py b/src/arch/x86/isa/insts/system/__init__.py new file mode 100644 index 000000000..72e3bdf0a --- /dev/null +++ b/src/arch/x86/isa/insts/system/__init__.py @@ -0,0 +1,62 @@ +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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 + +categories = ["undefined_operation"] + +microcode = "" +for category in categories: + exec "import %s as cat" % category + microcode += cat.microcode + diff --git a/src/arch/x86/isa/insts/system/undefined_operation.py b/src/arch/x86/isa/insts/system/undefined_operation.py new file mode 100644 index 000000000..e5544b6e7 --- /dev/null +++ b/src/arch/x86/isa/insts/system/undefined_operation.py @@ -0,0 +1,61 @@ +# Copyright (c) 2007 The Hewlett-Packard Development Company +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the +# following conditions are met: +# +# The software must be used only for Non-Commercial Use which means any +# use which is NOT directed to receiving any direct monetary +# compensation for, or commercial advantage from such use. Illustrative +# examples of non-commercial use are academic research, personal study, +# teaching, education and corporate research & development. +# Illustrative examples of commercial use are distributing products for +# commercial advantage and providing services using the software for +# commercial advantage. +# +# If you wish to use this software or functionality therein that may be +# covered by patents for commercial use, please contact: +# Director of Intellectual Property Licensing +# Office of Strategy and Technology +# Hewlett-Packard Company +# 1501 Page Mill Road +# Palo Alto, California 94304 +# +# 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. No right of +# sublicense is granted herewith. Derivatives of the software and +# output created using the software may be prepared, but only for +# Non-Commercial Uses. Derivatives of the software may be shared with +# others provided: (i) the others agree to abide by the list of +# conditions herein which includes the Non-Commercial Use restrictions; +# and (ii) such Derivatives of the software include the above copyright +# notice to acknowledge the contribution from this software where +# applicable, this list of conditions and the disclaimer below. +# +# 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 + +microcode = ''' +def macroop UD2 +{ + fault "new X86Fault" +}; +''' diff --git a/src/arch/x86/isa/main.isa b/src/arch/x86/isa/main.isa index fed8903c0..73cebc12b 100644 --- a/src/arch/x86/isa/main.isa +++ b/src/arch/x86/isa/main.isa @@ -79,8 +79,8 @@ namespace X86ISA; //Include the bitfield definitions ##include "bitfields.isa" -//Include the base class for x86 instructions, and some support code. -##include "base.isa" +//Include the OutputBlocks class which is used to bundle output. +##include "outputblock.isa" //Include the definitions for the instruction formats ##include "formats/formats.isa" diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa index ee2b92f53..213468b0b 100644 --- a/src/arch/x86/isa/microasm.isa +++ b/src/arch/x86/isa/microasm.isa @@ -56,9 +56,9 @@ // Authors: Gabe Black //Include the definitions of the micro ops. -//These are StaticInst classes which stand on their own and make up an -//internal instruction set, and also python representations which are passed -//into the microcode assembler. +//These are python representations of static insts which stand on their own +//and make up an internal instruction set. They are used by the micro +//assembler. ##include "microops/microops.isa" //Include code to build macroops in both C++ and python. @@ -96,6 +96,19 @@ let {{ assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper() assembler.symbols.update(symbols) + for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF'): + assembler.symbols[flag] = flag + "Bit" + + for cond in ('True', 'False', 'ECF', 'EZF', 'SZnZF', + 'MSTRZ', 'STRZ', 'MSTRC', 'STRZnZF', + 'OF', 'CF', 'ZF', 'CvZF', + 'SF', 'PF', 'SxOF', 'SxOvZF'): + assembler.symbols["C%s" % cond] = "ConditionTests::%s" % cond + assembler.symbols["nC%s" % cond] = "ConditionTests::Not%s" % cond + + assembler.symbols["CTrue"] = "ConditionTests::True" + assembler.symbols["CFalse"] = "ConditionTests::False" + # Code literal which forces a default 64 bit operand size in 64 bit mode. assembler.symbols["oszIn64Override"] = ''' if (machInst.mode.submode == SixtyFourBitMode && diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 79ac4493a..71fc3b3a5 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -61,42 +61,6 @@ let {{ microopClasses = {} }}; -//A class which is the base of all x86 micro ops. It provides a function to -//set necessary flags appropriately. -output header {{ - class X86MicroopBase : public X86StaticInst - { - protected: - const char * instMnem; - uint8_t opSize; - uint8_t addrSize; - - X86MicroopBase(ExtMachInst _machInst, - const char *mnem, const char *_instMnem, - bool isMicro, bool isDelayed, - bool isFirst, bool isLast, - OpClass __opClass) : - X86StaticInst(mnem, _machInst, __opClass), - instMnem(_instMnem) - { - flags[IsMicroop] = isMicro; - flags[IsDelayedCommit] = isDelayed; - flags[IsFirstMicroop] = isFirst; - flags[IsLastMicroop] = isLast; - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream ss; - - ccprintf(ss, "\t%s.%s", instMnem, mnemonic); - - return ss.str(); - } - }; -}}; - ////////////////////////////////////////////////////////////////////////// // // Base class for the python representation of x86 microops diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa index fbff899a0..ccf519963 100644 --- a/src/arch/x86/isa/microops/ldstop.isa +++ b/src/arch/x86/isa/microops/ldstop.isa @@ -59,63 +59,6 @@ // ////////////////////////////////////////////////////////////////////////// -output header {{ - /** - * Base class for load and store ops - */ - class LdStOp : public X86MicroopBase - { - protected: - const uint8_t scale; - const RegIndex index; - const RegIndex base; - const uint64_t disp; - const uint8_t segment; - const RegIndex data; - const uint8_t dataSize; - const uint8_t addressSize; - - //Constructor - LdStOp(ExtMachInst _machInst, - const char * mnem, const char * _instMnem, - bool isMicro, bool isDelayed, bool isFirst, bool isLast, - uint8_t _scale, RegIndex _index, RegIndex _base, - uint64_t _disp, uint8_t _segment, - RegIndex _data, - uint8_t _dataSize, uint8_t _addressSize, - OpClass __opClass) : - X86MicroopBase(machInst, mnem, _instMnem, - isMicro, isDelayed, isFirst, isLast, __opClass), - scale(_scale), index(_index), base(_base), - disp(_disp), segment(_segment), - data(_data), - dataSize(_dataSize), addressSize(_addressSize) - {} - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - }; -}}; - -output decoder {{ - std::string LdStOp::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - - printMnemonic(response, instMnem, mnemonic); - printReg(response, data); - response << ", "; - printSegment(response, segment); - ccprintf(response, ":[%d*", scale); - printReg(response, index); - response << " + "; - printReg(response, base); - ccprintf(response, " + %#x]", disp); - return response.str(); - } -}}; - // LEA template def template MicroLeaExecute {{ @@ -180,7 +123,25 @@ def template MicroLoadExecute {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0); + unsigned flags = 0; + switch(dataSize) + { + case 1: + fault = xc->read(EA, (uint8_t&)Mem, flags); + break; + case 2: + fault = xc->read(EA, (uint16_t&)Mem, flags); + break; + case 4: + fault = xc->read(EA, (uint32_t&)Mem, flags); + break; + case 8: + fault = xc->read(EA, (uint64_t&)Mem, flags); + break; + default: + panic("Bad operand size!\n"); + } + if(fault == NoFault) { %(code)s; @@ -206,7 +167,24 @@ def template MicroLoadInitiateAcc {{ %(ea_code)s; DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); - fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, 0); + unsigned flags = 0; + switch(dataSize) + { + case 1: + fault = xc->read(EA, (uint8_t&)Mem, flags); + break; + case 2: + fault = xc->read(EA, (uint16_t&)Mem, flags); + break; + case 4: + fault = xc->read(EA, (uint32_t&)Mem, flags); + break; + case 8: + fault = xc->read(EA, (uint64_t&)Mem, flags); + break; + default: + panic("Bad operand size!\n"); + } return fault; } @@ -252,8 +230,25 @@ def template MicroStoreExecute {{ if(fault == NoFault) { - fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, - EA, 0, 0); + unsigned flags = 0; + uint64_t *res = 0; + switch(dataSize) + { + case 1: + fault = xc->write((uint8_t&)Mem, EA, flags, res); + break; + case 2: + fault = xc->write((uint16_t&)Mem, EA, flags, res); + break; + case 4: + fault = xc->write((uint32_t&)Mem, EA, flags, res); + break; + case 8: + fault = xc->write((uint64_t&)Mem, EA, flags, res); + break; + default: + panic("Bad operand size!\n"); + } } if(fault == NoFault) { @@ -280,8 +275,25 @@ def template MicroStoreInitiateAcc {{ if(fault == NoFault) { - fault = xc->write((%(mem_acc_type)s%(mem_acc_size)s_t)Mem, - EA, 0, 0); + unsigned flags = 0; + uint64_t *res = 0; + switch(dataSize) + { + case 1: + fault = xc->write((uint8_t&)Mem, EA, flags, res); + break; + case 2: + fault = xc->write((uint16_t&)Mem, EA, flags, res); + break; + case 4: + fault = xc->write((uint32_t&)Mem, EA, flags, res); + break; + case 8: + fault = xc->write((uint64_t&)Mem, EA, flags, res); + break; + default: + panic("Bad operand size!\n"); + } } if(fault == NoFault) { @@ -382,12 +394,12 @@ def template MicroLdStOpConstructor {{ let {{ class LdStOp(X86Microop): - def __init__(self, data, segment, addr, disp): + def __init__(self, data, segment, addr, disp, dataSize): self.data = data [self.scale, self.index, self.base] = addr self.disp = disp self.segment = segment - self.dataSize = "env.dataSize" + self.dataSize = dataSize self.addressSize = "env.addressSize" def getAllocator(self, *microFlags): @@ -424,7 +436,7 @@ let {{ name = mnemonic.lower() # Build up the all register version of this micro op - iop = InstObjParams(name, Name, 'LdStOp', + iop = InstObjParams(name, Name, 'X86ISA::LdStOp', {"code": code, "ea_code": calculateEA}) header_output += MicroLdStOpDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) @@ -433,8 +445,10 @@ let {{ exec_output += MicroLoadCompleteAcc.subst(iop) class LoadOp(LdStOp): - def __init__(self, data, segment, addr, disp = 0): - super(LoadOp, self).__init__(data, segment, addr, disp) + def __init__(self, data, segment, addr, + disp = 0, dataSize="env.dataSize"): + super(LoadOp, self).__init__(data, segment, + addr, disp, dataSize) self.className = Name self.mnemonic = name @@ -451,7 +465,7 @@ let {{ name = mnemonic.lower() # Build up the all register version of this micro op - iop = InstObjParams(name, Name, 'LdStOp', + iop = InstObjParams(name, Name, 'X86ISA::LdStOp', {"code": code, "ea_code": calculateEA}) header_output += MicroLdStOpDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) @@ -460,24 +474,28 @@ let {{ exec_output += MicroStoreCompleteAcc.subst(iop) class StoreOp(LdStOp): - def __init__(self, data, segment, addr, disp = 0): - super(LoadOp, self).__init__(data, segment, addr, disp) + def __init__(self, data, segment, addr, + disp = 0, dataSize="env.dataSize"): + super(StoreOp, self).__init__(data, segment, + addr, disp, dataSize) self.className = Name self.mnemonic = name microopClasses[name] = StoreOp - defineMicroLoadOp('St', 'Mem = Data;') + defineMicroStoreOp('St', 'Mem = Data;') - iop = InstObjParams("lea", "Lea", 'LdStOp', + iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp', {"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA}) header_output += MicroLeaDeclare.subst(iop) decoder_output += MicroLdStOpConstructor.subst(iop) exec_output += MicroLeaExecute.subst(iop) class LeaOp(LdStOp): - def __init__(self, data, segment, addr, disp = 0): - super(LeaOp, self).__init__(data, segment, addr, disp) + def __init__(self, data, segment, addr, + disp = 0, dataSize="env.dataSize"): + super(LeaOp, self).__init__(data, segment, + addr, disp, dataSize) self.className = "Lea" self.mnemonic = "lea" diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa index 141d7523f..37180d7fa 100644 --- a/src/arch/x86/isa/microops/limmop.isa +++ b/src/arch/x86/isa/microops/limmop.isa @@ -72,11 +72,12 @@ def template MicroLimmOpExecute {{ }}; def template MicroLimmOpDeclare {{ - class %(class_name)s : public X86MicroopBase + class %(class_name)s : public X86ISA::X86MicroopBase { protected: const RegIndex dest; const uint64_t imm; + const uint8_t dataSize; void buildMe(); std::string generateDisassembly(Addr pc, @@ -86,11 +87,11 @@ def template MicroLimmOpDeclare {{ %(class_name)s(ExtMachInst _machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, - RegIndex _dest, uint64_t _imm); + RegIndex _dest, uint64_t _imm, uint8_t _dataSize); %(class_name)s(ExtMachInst _machInst, const char * instMnem, - RegIndex _dest, uint64_t _imm); + RegIndex _dest, uint64_t _imm, uint8_t _dataSize); %(BasicExecDeclare)s }; @@ -103,7 +104,7 @@ def template MicroLimmOpDisassembly {{ std::stringstream response; printMnemonic(response, instMnem, mnemonic); - printReg(response, dest); + printReg(response, dest, dataSize); response << ", "; ccprintf(response, "%#x", imm); return response.str(); @@ -119,10 +120,10 @@ def template MicroLimmOpConstructor {{ inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, - RegIndex _dest, uint64_t _imm) : + RegIndex _dest, uint64_t _imm, uint8_t _dataSize) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, %(op_class)s), - dest(_dest), imm(_imm) + dest(_dest), imm(_imm), dataSize(_dataSize) { buildMe(); } @@ -130,10 +131,10 @@ def template MicroLimmOpConstructor {{ inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, - RegIndex _dest, uint64_t _imm) : + RegIndex _dest, uint64_t _imm, uint8_t _dataSize) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, %(op_class)s), - dest(_dest), imm(_imm) + dest(_dest), imm(_imm), dataSize(_dataSize) { buildMe(); } @@ -146,14 +147,16 @@ let {{ self.mnemonic = "limm" self.dest = dest self.imm = imm + self.dataSize = "env.dataSize" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, mnemonic - %(flags)s, %(dest)s, %(imm)s)''' % { + %(flags)s, %(dest)s, %(imm)s, %(dataSize)s)''' % { "class_name" : self.className, "mnemonic" : self.mnemonic, "flags" : self.microFlagsText(microFlags), - "dest" : self.dest, "imm" : self.imm } + "dest" : self.dest, "imm" : self.imm, + "dataSize" : self.dataSize} return allocator microopClasses["limm"] = LimmOp diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 65b75fab8..dbbe11c90 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -59,100 +59,6 @@ // ////////////////////////////////////////////////////////////////////////// -output header {{ - /** - * Base classes for RegOps which provides a generateDisassembly method. - */ - class RegOp : public X86MicroopBase - { - protected: - const RegIndex src1; - const RegIndex src2; - const RegIndex dest; - const bool setStatus; - const uint8_t dataSize; - const uint8_t ext; - - // Constructor - RegOp(ExtMachInst _machInst, - const char *mnem, const char *_instMnem, - bool isMicro, bool isDelayed, - bool isFirst, bool isLast, - RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext, - OpClass __opClass) : - X86MicroopBase(_machInst, mnem, _instMnem, - isMicro, isDelayed, isFirst, isLast, - __opClass), - src1(_src1), src2(_src2), dest(_dest), - setStatus(_setStatus), dataSize(_dataSize), ext(_ext) - { - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - }; - - class RegOpImm : public X86MicroopBase - { - protected: - const RegIndex src1; - const uint8_t imm8; - const RegIndex dest; - const bool setStatus; - const uint8_t dataSize; - const uint8_t ext; - - // Constructor - RegOpImm(ExtMachInst _machInst, - const char * mnem, const char *_instMnem, - bool isMicro, bool isDelayed, - bool isFirst, bool isLast, - RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext, - OpClass __opClass) : - X86MicroopBase(_machInst, mnem, _instMnem, - isMicro, isDelayed, isFirst, isLast, - __opClass), - src1(_src1), imm8(_imm8), dest(_dest), - setStatus(_setStatus), dataSize(_dataSize), ext(_ext) - { - } - - std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) const; - }; -}}; - -output decoder {{ - std::string RegOp::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - - printMnemonic(response, instMnem, mnemonic); - printReg(response, dest); - response << ", "; - printReg(response, src1); - response << ", "; - printReg(response, src2); - return response.str(); - } - - std::string RegOpImm::generateDisassembly(Addr pc, - const SymbolTable *symtab) const - { - std::stringstream response; - - printMnemonic(response, instMnem, mnemonic); - printReg(response, dest); - response << ", "; - printReg(response, src1); - ccprintf(response, ", %#x", imm8); - return response.str(); - } -}}; - def template MicroRegOpExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const @@ -161,8 +67,16 @@ def template MicroRegOpExecute {{ %(op_decl)s; %(op_rd)s; - %(code)s; - %(flag_code)s; + + if(%(cond_check)s) + { + %(code)s; + %(flag_code)s; + } + else + { + %(else_code)s; + } //Write the resulting state to the execution context if(fault == NoFault) @@ -181,8 +95,16 @@ def template MicroRegOpImmExecute {{ %(op_decl)s; %(op_rd)s; - %(code)s; - %(flag_code)s; + + if(%(cond_check)s) + { + %(code)s; + %(flag_code)s; + } + else + { + %(else_code)s; + } //Write the resulting state to the execution context if(fault == NoFault) @@ -204,12 +126,12 @@ def template MicroRegOpDeclare {{ const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext); + uint8_t _dataSize, uint16_t _ext); %(class_name)s(ExtMachInst _machInst, const char * instMnem, RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext); + uint8_t _dataSize, uint16_t _ext); %(BasicExecDeclare)s }; @@ -227,12 +149,12 @@ def template MicroRegOpImmDeclare {{ const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext); + uint8_t _dataSize, uint16_t _ext); %(class_name)sImm(ExtMachInst _machInst, const char * instMnem, RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext); + uint8_t _dataSize, uint16_t _ext); %(BasicExecDeclare)s }; @@ -248,10 +170,10 @@ def template MicroRegOpConstructor {{ inline %(class_name)s::%(class_name)s( ExtMachInst machInst, const char * instMnem, RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext) : + uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, - _src1, _src2, _dest, _setStatus, _dataSize, _ext, + _src1, _src2, _dest, _dataSize, _ext, %(op_class)s) { buildMe(); @@ -261,10 +183,10 @@ def template MicroRegOpConstructor {{ ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, RegIndex _src1, RegIndex _src2, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext) : + uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, - _src1, _src2, _dest, _setStatus, _dataSize, _ext, + _src1, _src2, _dest, _dataSize, _ext, %(op_class)s) { buildMe(); @@ -281,10 +203,10 @@ def template MicroRegOpImmConstructor {{ inline %(class_name)sImm::%(class_name)sImm( ExtMachInst machInst, const char * instMnem, RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext) : + uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, false, false, false, false, - _src1, _imm8, _dest, _setStatus, _dataSize, _ext, + _src1, _imm8, _dest, _dataSize, _ext, %(op_class)s) { buildMe(); @@ -294,10 +216,10 @@ def template MicroRegOpImmConstructor {{ ExtMachInst machInst, const char * instMnem, bool isMicro, bool isDelayed, bool isFirst, bool isLast, RegIndex _src1, uint8_t _imm8, RegIndex _dest, - bool _setStatus, uint8_t _dataSize, uint8_t _ext) : + uint8_t _dataSize, uint16_t _ext) : %(base_class)s(machInst, "%(mnemonic)s", instMnem, isMicro, isDelayed, isFirst, isLast, - _src1, _imm8, _dest, _setStatus, _dataSize, _ext, + _src1, _imm8, _dest, _dataSize, _ext, %(op_class)s) { buildMe(); @@ -305,46 +227,74 @@ def template MicroRegOpImmConstructor {{ }}; let {{ + class X86MicroMeta(type): + def __new__(mcls, name, bases, dict): + abstract = False + if "abstract" in dict: + abstract = dict['abstract'] + del dict['abstract'] + + cls = type.__new__(mcls, name, bases, dict) + if not abstract: + allClasses[name] = cls + return cls + + class XXX86Microop(object): + __metaclass__ = X86MicroMeta + abstract = True + class RegOp(X86Microop): - def __init__(self, dest, src1, src2, setStatus): + abstract = True + def __init__(self, dest, src1, src2, flags, dataSize): self.dest = dest self.src1 = src1 self.src2 = src2 - self.setStatus = setStatus - self.dataSize = "env.dataSize" - self.ext = 0 + self.flags = flags + self.dataSize = dataSize + if flags is None: + self.ext = 0 + else: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.ext = " | ".join(flags) + self.className += "Flags" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, mnemonic %(flags)s, %(src1)s, %(src2)s, %(dest)s, - %(setStatus)s, %(dataSize)s, %(ext)s)''' % { + %(dataSize)s, %(ext)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), "src1" : self.src1, "src2" : self.src2, "dest" : self.dest, - "setStatus" : self.cppBool(self.setStatus), "dataSize" : self.dataSize, "ext" : self.ext} return allocator class RegOpImm(X86Microop): - def __init__(self, dest, src1, imm8, setStatus): + abstract = True + def __init__(self, dest, src1, imm8, flags, dataSize): self.dest = dest self.src1 = src1 self.imm8 = imm8 - self.setStatus = setStatus - self.dataSize = "env.dataSize" - self.ext = 0 + self.flags = flags + self.dataSize = dataSize + if flags is None: + self.ext = 0 + else: + if not isinstance(flags, (list, tuple)): + raise Exception, "flags must be a list or tuple of flags" + self.ext = " | ".join(flags) + self.className += "Flags" def getAllocator(self, *microFlags): allocator = '''new %(class_name)s(machInst, mnemonic %(flags)s, %(src1)s, %(imm8)s, %(dest)s, - %(setStatus)s, %(dataSize)s, %(ext)s)''' % { + %(dataSize)s, %(ext)s)''' % { "class_name" : self.className, "flags" : self.microFlagsText(microFlags), "src1" : self.src1, "imm8" : self.imm8, "dest" : self.dest, - "setStatus" : self.cppBool(self.setStatus), "dataSize" : self.dataSize, "ext" : self.ext} return allocator @@ -358,7 +308,8 @@ let {{ decoder_output = "" exec_output = "" - def setUpMicroRegOp(name, Name, base, code, child, flagCode): + # A function which builds the C++ classes that implement the microops + def setUpMicroRegOp(name, Name, base, code, flagCode = "", condCheck = "true", elseCode = ";"): global header_output global decoder_output global exec_output @@ -366,14 +317,21 @@ let {{ iop = InstObjParams(name, Name, base, {"code" : code, - "flag_code" : flagCode}) + "flag_code" : flagCode, + "cond_check" : condCheck, + "else_code" : elseCode}) header_output += MicroRegOpDeclare.subst(iop) decoder_output += MicroRegOpConstructor.subst(iop) exec_output += MicroRegOpExecute.subst(iop) - microopClasses[name] = child - def defineMicroRegOp(mnemonic, code, flagCode): + checkCCFlagBits = "checkCondition(ccFlagBits)" + genCCFlagBits = "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, SrcReg1, %s);" + + + # This creates a python representations of a microop which are a cross + # product of reg/immediate and flag/no flag versions. + def defineMicroRegOp(mnemonic, code, subtract = False, cc=False, elseCode=";"): Name = mnemonic name = mnemonic.lower() @@ -384,36 +342,47 @@ let {{ regCode = matcher.sub("SrcReg2", code) immCode = matcher.sub("imm8", code) - # Build the all register version of this micro op + if subtract: + secondSrc = "-op2, true" + else: + secondSrc = "op2" + + if not cc: + flagCode = genCCFlagBits % secondSrc + condCode = "true" + else: + flagCode = "" + condCode = checkCCFlagBits + + regFlagCode = matcher.sub("SrcReg2", flagCode) + immFlagCode = matcher.sub("imm8", flagCode) + class RegOpChild(RegOp): - def __init__(self, dest, src1, src2, setStatus=False): - super(RegOpChild, self).__init__(dest, src1, src2, setStatus) - self.className = Name - self.mnemonic = name + mnemonic = name + className = Name + def __init__(self, dest, src1, src2, flags=None, dataSize="env.dataSize"): + super(RegOpChild, self).__init__(dest, src1, src2, flags, dataSize) + + microopClasses[name] = RegOpChild - setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild, flagCode); + setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode); + setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, + flagCode = regFlagCode, condCheck = condCode, elseCode = elseCode); - # Build the immediate version of this micro op class RegOpChildImm(RegOpImm): - def __init__(self, dest, src1, src2, setStatus=False): - super(RegOpChildImm, self).__init__(dest, src1, src2, setStatus) - self.className = Name + "Imm" - self.mnemonic = name + "i" - - setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm, flagCode); - - defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to set OF,CF,SF - defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)', "") - defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)', "") #Needs to add in CF, set OF,CF,SF - defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to subtract CF, set OF,CF,SF - defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)', "") - defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', "") #Needs to set OF,CF,SF - defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)', "") - defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', "") #Needs to set OF,CF,SF and not DestReg - defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', "") + mnemonic = name + 'i' + className = Name + 'Imm' + def __init__(self, dest, src1, src2, flags=None, dataSize="env.dataSize"): + super(RegOpChildImm, self).__init__(dest, src1, src2, flags, dataSize) + + microopClasses[name + 'i'] = RegOpChildImm + + setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", immCode); + setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm", immCode, + flagCode = immFlagCode, condCheck = condCode, elseCode = elseCode); # This has it's own function because Wr ops have implicit destinations - def defineMicroRegOpWr(mnemonic, code): + def defineMicroRegOpWr(mnemonic, code, elseCode=";"): Name = mnemonic name = mnemonic.lower() @@ -424,25 +393,29 @@ let {{ regCode = matcher.sub("SrcReg2", code) immCode = matcher.sub("imm8", code) - # Build the all register version of this micro op class RegOpChild(RegOp): - def __init__(self, src1, src2): - super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, False) - self.className = Name - self.mnemonic = name + mnemonic = name + className = Name + def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): + super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) + + microopClasses[name] = RegOpChild - setUpMicroRegOp(name, Name, "RegOp", regCode, RegOpChild, ""); + setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode); + setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, + condCheck = checkCCFlagBits, elseCode = elseCode); - # Build the immediate version of this micro op class RegOpChildImm(RegOpImm): - def __init__(self, src1, src2): - super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, False) - self.className = Name + "Imm" - self.mnemonic = name + "i" + mnemonic = name + 'i' + className = Name + 'Imm' + def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"): + super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize) - setUpMicroRegOp(name + "i", Name + "Imm", "RegOpImm", immCode, RegOpChildImm, ""); + microopClasses[name + 'i'] = RegOpChildImm - defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2') + setUpMicroRegOp(name + 'i', Name + "Imm", "X86ISA::RegOpImm", immCode); + setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", immCode, + condCheck = checkCCFlagBits, elseCode = elseCode); # This has it's own function because Rd ops don't always have two parameters def defineMicroRegOpRd(mnemonic, code): @@ -450,30 +423,136 @@ let {{ name = mnemonic.lower() class RegOpChild(RegOp): - def __init__(self, dest, src1 = "NUM_INTREGS"): - super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", False) + def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"): + super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize) self.className = Name self.mnemonic = name - setUpMicroRegOp(name, Name, "RegOp", code, RegOpChild, ""); + microopClasses[name] = RegOpChild - defineMicroRegOpRd('Rdip', 'DestReg = RIP') + setUpMicroRegOp(name, Name, "X86ISA::RegOp", code); def defineMicroRegOpImm(mnemonic, code): Name = mnemonic name = mnemonic.lower() class RegOpChild(RegOpImm): - def __init__(self, dest, src1, src2): - super(RegOpChild, self).__init__(dest, src1, src2, False) + def __init__(self, dest, src1, src2, dataSize="env.dataSize"): + super(RegOpChild, self).__init__(dest, src1, src2, None, dataSize) self.className = Name self.mnemonic = name - setUpMicroRegOp(name, Name, "RegOpImm", code, RegOpChild, ""); + microopClasses[name] = RegOpChild + + setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code); + + defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') + defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)') + defineMicroRegOp('Adc', ''' + CCFlagBits flags = ccFlagBits; + DestReg = merge(DestReg, SrcReg1 + op2 + flags.CF, dataSize); + ''') + defineMicroRegOp('Sbb', ''' + CCFlagBits flags = ccFlagBits; + DestReg = merge(DestReg, SrcReg1 - op2 - flags.CF, dataSize); + ''', True) + defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)') + defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', True) + defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)') + # defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', True) + defineMicroRegOp('Mul1s', 'DestReg = merge(DestReg, DestReg * op2, dataSize)') + defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)', + elseCode='DestReg=DestReg;', cc=True) + + # Shift instructions + defineMicroRegOp('Sll', ''' + uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + DestReg = merge(DestReg, SrcReg1 << shiftAmt, dataSize); + ''') + defineMicroRegOp('Srl', ''' + uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + // Because what happens to the bits shift -in- on a right shift + // is not defined in the C/C++ standard, we have to mask them out + // to be sure they're zero. + uint64_t logicalMask = mask(dataSize * 8 - shiftAmt); + DestReg = merge(DestReg, (SrcReg1 >> shiftAmt) & logicalMask, dataSize); + ''') + defineMicroRegOp('Sra', ''' + uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + // Because what happens to the bits shift -in- on a right shift + // is not defined in the C/C++ standard, we have to sign extend + // them manually to be sure. + uint64_t arithMask = + -bits(op2, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt); + DestReg = merge(DestReg, (SrcReg1 >> shiftAmt) | arithMask, dataSize); + ''') + defineMicroRegOp('Ror', ''' + uint8_t shiftAmt = + (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + if(shiftAmt) + { + uint64_t top = SrcReg1 << (dataSize * 8 - shiftAmt); + uint64_t bottom = bits(SrcReg1, dataSize * 8, shiftAmt); + DestReg = merge(DestReg, top | bottom, dataSize); + } + else + DestReg = DestReg; + ''') + defineMicroRegOp('Rcr', ''' + uint8_t shiftAmt = + (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + if(shiftAmt) + { + CCFlagBits flags = ccFlagBits; + uint64_t top = flags.CF << (dataSize * 8 - shiftAmt); + if(shiftAmt > 1) + top |= SrcReg1 << (dataSize * 8 - shiftAmt - 1); + uint64_t bottom = bits(SrcReg1, dataSize * 8, shiftAmt); + DestReg = merge(DestReg, top | bottom, dataSize); + } + else + DestReg = DestReg; + ''') + defineMicroRegOp('Rol', ''' + uint8_t shiftAmt = + (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + if(shiftAmt) + { + uint64_t top = SrcReg1 << shiftAmt; + uint64_t bottom = + bits(SrcReg1, dataSize * 8 - 1, dataSize * 8 - shiftAmt); + DestReg = merge(DestReg, top | bottom, dataSize); + } + else + DestReg = DestReg; + ''') + defineMicroRegOp('Rcl', ''' + uint8_t shiftAmt = + (op2 & ((dataSize == 8) ? mask(4) : mask(3))); + if(shiftAmt) + { + CCFlagBits flags = ccFlagBits; + uint64_t top = SrcReg1 << shiftAmt; + uint64_t bottom = flags.CF << (shiftAmt - 1); + if(shiftAmt > 1) + bottom |= + bits(SrcReg1, dataSize * 8 - 1, + dataSize * 8 - shiftAmt + 1); + DestReg = merge(DestReg, top | bottom, dataSize); + } + else + DestReg = DestReg; + ''') + + defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2', elseCode="RIP = RIP;") + + defineMicroRegOpRd('Rdip', 'DestReg = RIP') defineMicroRegOpImm('Sext', ''' IntReg val = SrcReg1; int sign_bit = bits(val, imm8-1, imm8-1); val = sign_bit ? (val | ~mask(imm8)) : val; DestReg = merge(DestReg, val, dataSize);''') + + defineMicroRegOpImm('Zext', 'DestReg = bits(SrcReg1, imm8-1, 0);') }}; diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa index b56223390..5c9e8dda9 100644 --- a/src/arch/x86/isa/microops/specop.isa +++ b/src/arch/x86/isa/microops/specop.isa @@ -60,7 +60,7 @@ ////////////////////////////////////////////////////////////////////////// output header {{ - class MicroFault : public X86MicroopBase + class MicroFault : public X86ISA::X86MicroopBase { protected: Fault fault; @@ -75,6 +75,9 @@ output header {{ Fault _fault); %(BasicExecDeclare)s + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; }; }}; @@ -106,6 +109,22 @@ output decoder {{ } }}; +output decoder {{ + std::string MicroFault::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, instMnem, mnemonic); + if(fault) + response << fault->name(); + else + response << "No Fault"; + + return response.str(); + } +}}; + let {{ class Fault(X86Microop): def __init__(self, fault): diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa index b2ac17d66..406c74a1f 100644 --- a/src/arch/x86/isa/operands.isa +++ b/src/arch/x86/isa/operands.isa @@ -102,6 +102,8 @@ def operands {{ 'Base': ('IntReg', 'uqw', 'base', 'IsInteger', 4), 'Index': ('IntReg', 'uqw', 'index', 'IsInteger', 5), 'Data': ('IntReg', 'uqw', 'data', 'IsInteger', 6), + 'rax': ('IntReg', 'uqw', 'INTREG_RAX', 'IsInteger', 7), 'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 10), + 'ccFlagBits': ('IntReg', 'uqw', 'NUM_INTREGS + NumMicroIntRegs', None, 20), 'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) }}; diff --git a/src/arch/x86/isa/outputblock.isa b/src/arch/x86/isa/outputblock.isa new file mode 100644 index 000000000..342d6ac4b --- /dev/null +++ b/src/arch/x86/isa/outputblock.isa @@ -0,0 +1,91 @@ +// Copyright (c) 2007 The Hewlett-Packard Development Company +// All rights reserved. +// +// Redistribution and use of this software in source and binary forms, +// with or without modification, are permitted provided that the +// following conditions are met: +// +// The software must be used only for Non-Commercial Use which means any +// use which is NOT directed to receiving any direct monetary +// compensation for, or commercial advantage from such use. Illustrative +// examples of non-commercial use are academic research, personal study, +// teaching, education and corporate research & development. +// Illustrative examples of commercial use are distributing products for +// commercial advantage and providing services using the software for +// commercial advantage. +// +// If you wish to use this software or functionality therein that may be +// covered by patents for commercial use, please contact: +// Director of Intellectual Property Licensing +// Office of Strategy and Technology +// Hewlett-Packard Company +// 1501 Page Mill Road +// Palo Alto, California 94304 +// +// 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. No right of +// sublicense is granted herewith. Derivatives of the software and +// output created using the software may be prepared, but only for +// Non-Commercial Uses. Derivatives of the software may be shared with +// others provided: (i) the others agree to abide by the list of +// conditions herein which includes the Non-Commercial Use restrictions; +// and (ii) such Derivatives of the software include the above copyright +// notice to acknowledge the contribution from this software where +// applicable, this list of conditions and the disclaimer below. +// +// 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 + +//////////////////////////////////////////////////////////////////// +// +// Output blocks which group together code generated by the parser. +// + +let {{ + # This class will help make dealing with output a little less verbose + class OutputBlocks(object): + def __init__(self, header_output="", + decoder_output="", + decode_block="", + exec_output=""): + self.header_output = header_output + self.decoder_output = decoder_output + self.decode_block = decode_block + self.exec_output = exec_output + + def append(self, blocks): + if isinstance(blocks, list) or isinstance(blocks, tuple): + assert(len(blocks) == 4) + self.header_output += blocks[0] + self.decoder_output += blocks[1] + self.decode_block += blocks[2] + self.exec_output += blocks[3] + else: + self.header_output += blocks.header_output + self.decoder_output += blocks.decoder_output + self.decode_block += blocks.decode_block + self.exec_output += blocks.exec_output + + def makeList(self): + return (self.header_output, + self.decoder_output, + self.decode_block, + self.exec_output) +}}; diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa index 3183f32ba..5165ea206 100644 --- a/src/arch/x86/isa/specialize.isa +++ b/src/arch/x86/isa/specialize.isa @@ -118,6 +118,7 @@ let {{ ModRMRegIndex = "(MODRM_REG | (REX_R << 3))" ModRMRMIndex = "(MODRM_RM | (REX_B << 3))" + InstRegIndex = "(OPCODE_OP_BOTTOM3 | (REX_B << 3))" # This function specializes the given piece of code to use a particular # set of argument types described by "opTypes". @@ -143,6 +144,10 @@ let {{ else: print "Didn't recognize fixed register size %s!" % opType.rsize Name += "_R" + elif opType.tag == "B": + # This refers to registers whose index is encoded as part of the opcode + Name += "_R" + env.addReg(InstRegIndex) elif opType.tag == "M": # This refers to memory. The macroop constructor sets up modrm # addressing. Non memory modrm settings should cause an error. diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index 809784635..30360e602 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -56,6 +56,7 @@ */ #include "arch/x86/linux/process.hh" +#include "arch/x86/linux/linux.hh" #include "kern/linux/linux.hh" #include "sim/syscall_emul.hh" @@ -82,7 +83,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, SyscallDesc X86LinuxProcess::syscallDescs[] = { /* 0 */ SyscallDesc("read", unimplementedFunc), /* 1 */ SyscallDesc("write", unimplementedFunc), - /* 2 */ SyscallDesc("open", unimplementedFunc), + /* 2 */ SyscallDesc("open", openFunc<X86Linux>), /* 3 */ SyscallDesc("close", unimplementedFunc), /* 4 */ SyscallDesc("stat", unimplementedFunc), /* 5 */ SyscallDesc("fstat", unimplementedFunc), diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc index 14ba3c7cc..9d8e94061 100644 --- a/src/arch/x86/miscregfile.cc +++ b/src/arch/x86/miscregfile.cc @@ -86,6 +86,7 @@ */ #include "arch/x86/miscregfile.hh" +#include "sim/serialize.hh" using namespace X86ISA; using namespace std; @@ -105,31 +106,65 @@ void MiscRegFile::clear() MiscReg MiscRegFile::readRegNoEffect(int miscReg) { - panic("No misc registers in x86 yet!\n"); + switch(miscReg) + { + case MISCREG_CR1: + case MISCREG_CR5: + case MISCREG_CR6: + case MISCREG_CR7: + case MISCREG_CR9: + case MISCREG_CR10: + case MISCREG_CR11: + case MISCREG_CR12: + case MISCREG_CR13: + case MISCREG_CR14: + case MISCREG_CR15: + panic("Tried to read invalid control register %d\n", miscReg); + break; + } + return regVal[miscReg]; } MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc) { - panic("No misc registers in x86 yet!\n"); + warn("No miscreg effects implemented yet!\n"); + return readRegNoEffect(miscReg); } void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val) { - panic("No misc registers in x86 yet!\n"); + switch(miscReg) + { + case MISCREG_CR1: + case MISCREG_CR5: + case MISCREG_CR6: + case MISCREG_CR7: + case MISCREG_CR9: + case MISCREG_CR10: + case MISCREG_CR11: + case MISCREG_CR12: + case MISCREG_CR13: + case MISCREG_CR14: + case MISCREG_CR15: + panic("Tried to write invalid control register %d\n", miscReg); + break; + } + regVal[miscReg] = val; } void MiscRegFile::setReg(int miscReg, const MiscReg &val, ThreadContext * tc) { - panic("No misc registers in x86 yet!\n"); + warn("No miscreg effects implemented yet!\n"); + setRegNoEffect(miscReg, val); } void MiscRegFile::serialize(std::ostream & os) { - panic("No misc registers in x86 yet!\n"); + SERIALIZE_ARRAY(regVal, NumMiscRegs); } void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section) { - panic("No misc registers in x86 yet!\n"); + UNSERIALIZE_ARRAY(regVal, NumMiscRegs); } diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh index 10acb97a4..e095e06e9 100644 --- a/src/arch/x86/miscregfile.hh +++ b/src/arch/x86/miscregfile.hh @@ -89,6 +89,7 @@ #define __ARCH_X86_MISCREGFILE_HH__ #include "arch/x86/faults.hh" +#include "arch/x86/miscregs.hh" #include "arch/x86/types.hh" #include <string> @@ -100,11 +101,14 @@ namespace X86ISA std::string getMiscRegName(RegIndex); //These will have to be updated in the future. - const int NumMiscArchRegs = 0; - const int NumMiscRegs = 0; + const int NumMiscArchRegs = NUM_MISCREGS; + const int NumMiscRegs = NUM_MISCREGS; class MiscRegFile { + protected: + MiscReg regVal[NumMiscRegs]; + public: void clear(); diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh new file mode 100644 index 000000000..39425fc9d --- /dev/null +++ b/src/arch/x86/miscregs.hh @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2007 The Hewlett-Packard Development Company + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, + * with or without modification, are permitted provided that the + * following conditions are met: + * + * The software must be used only for Non-Commercial Use which means any + * use which is NOT directed to receiving any direct monetary + * compensation for, or commercial advantage from such use. Illustrative + * examples of non-commercial use are academic research, personal study, + * teaching, education and corporate research & development. + * Illustrative examples of commercial use are distributing products for + * commercial advantage and providing services using the software for + * commercial advantage. + * + * If you wish to use this software or functionality therein that may be + * covered by patents for commercial use, please contact: + * Director of Intellectual Property Licensing + * Office of Strategy and Technology + * Hewlett-Packard Company + * 1501 Page Mill Road + * Palo Alto, California 94304 + * + * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. No right of + * sublicense is granted herewith. Derivatives of the software and + * output created using the software may be prepared, but only for + * Non-Commercial Uses. Derivatives of the software may be shared with + * others provided: (i) the others agree to abide by the list of + * conditions herein which includes the Non-Commercial Use restrictions; + * and (ii) such Derivatives of the software include the above copyright + * notice to acknowledge the contribution from this software where + * applicable, this list of conditions and the disclaimer below. + * + * 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 + */ + +#ifndef __ARCH_X86_MISCREGS_HH__ +#define __ARCH_X86_MISCREGS_HH__ + +#include "base/bitunion.hh" + +namespace X86ISA +{ + enum CondFlagBit { + CFBit = 1 << 0, + PFBit = 1 << 2, + ECFBit = 1 << 3, + AFBit = 1 << 4, + EZFBit = 1 << 5, + ZFBit = 1 << 6, + SFBit = 1 << 7, + OFBit = 1 << 11 + }; + + enum MiscRegIndex + { + // Control registers + // Most of these are invalid. + MISCREG_CR0, + MISCREG_CR1, + MISCREG_CR2, + MISCREG_CR3, + MISCREG_CR4, + MISCREG_CR5, + MISCREG_CR6, + MISCREG_CR7, + MISCREG_CR8, + MISCREG_CR9, + MISCREG_CR10, + MISCREG_CR11, + MISCREG_CR12, + MISCREG_CR13, + MISCREG_CR14, + MISCREG_CR15, + + // Debug registers + MISCREG_DR0, + MISCREG_DR1, + MISCREG_DR2, + MISCREG_DR3, + MISCREG_DR4, + MISCREG_DR5, + MISCREG_DR6, + MISCREG_DR7, + + // Flags register + MISCREG_RFLAGS, + + // Segment selectors + MISCREG_ES, + MISCREG_CS, + MISCREG_SS, + MISCREG_DS, + MISCREG_FS, + MISCREG_GS, + + // Hidden segment base field + MISCREG_ES_BASE, + MISCREG_CS_BASE, + MISCREG_SS_BASE, + MISCREG_DS_BASE, + MISCREG_FS_BASE, + MISCREG_GS_BASE, + + // Hidden segment limit field + MISCREG_ES_LIMIT, + MISCREG_CS_LIMIT, + MISCREG_SS_LIMIT, + MISCREG_DS_LIMIT, + MISCREG_FS_LIMIT, + MISCREG_GS_LIMIT, + + // Hidden segment limit attributes + MISCREG_ES_ATTR, + MISCREG_CS_ATTR, + MISCREG_SS_ATTR, + MISCREG_DS_ATTR, + MISCREG_FS_ATTR, + MISCREG_GS_ATTR, + + // System segment selectors + MISCREG_LDTR, + MISCREG_TR, + + // Hidden system segment base field + MISCREG_LDTR_BASE, + MISCREG_TR_BASE, + MISCREG_GDTR_BASE, + MISCREG_IDTR_BASE, + + // Hidden system segment limit field + MISCREG_LDTR_LIMIT, + MISCREG_TR_LIMIT, + MISCREG_GDTR_LIMIT, + MISCREG_IDTR_LIMIT, + + // Hidden system segment attribute field + MISCREG_LDTR_ATTR, + MISCREG_TR_ATTR, + + //XXX Add "Model-Specific Registers" + + NUM_MISCREGS + }; + + /** + * A type to describe the condition code bits of the RFLAGS register, + * plus two flags, EZF and ECF, which are only visible to microcode. + */ + BitUnion64(CCFlagBits) + Bitfield<11> OF; + Bitfield<7> SF; + Bitfield<6> ZF; + Bitfield<5> EZF; + Bitfield<4> AF; + Bitfield<3> ECF; + Bitfield<2> PF; + Bitfield<0> CF; + EndBitUnion(CCFlagBits) + + /** + * RFLAGS + */ + BitUnion64(RFLAGS) + Bitfield<21> ID; // ID Flag + Bitfield<20> VIP; // Virtual Interrupt Pending + Bitfield<19> VIF; // Virtual Interrupt Flag + Bitfield<18> AC; // Alignment Check + Bitfield<17> VM; // Virtual-8086 Mode + Bitfield<16> RF; // Resume Flag + Bitfield<14> NT; // Nested Task + Bitfield<13, 12> IOPL; // I/O Privilege Level + Bitfield<11> OF; // Overflow Flag + Bitfield<10> DF; // Direction Flag + Bitfield<9> IF; // Interrupt Flag + Bitfield<8> TF; // Trap Flag + Bitfield<7> SF; // Sign Flag + Bitfield<6> ZF; // Zero Flag + Bitfield<4> AF; // Auxiliary Flag + Bitfield<2> PF; // Parity Flag + Bitfield<0> CF; // Carry Flag + EndBitUnion(RFLAGS) + + /** + * Control registers + */ + BitUnion64(CR0) + Bitfield<31> PG; // Paging + Bitfield<30> CD; // Cache Disable + Bitfield<29> NW; // Not Writethrough + Bitfield<18> AM; // Alignment Mask + Bitfield<16> WP; // Write Protect + Bitfield<5> NE; // Numeric Error + Bitfield<4> ET; // Extension Type + Bitfield<3> TS; // Task Switched + Bitfield<2> EM; // Emulation + Bitfield<1> MP; // Monitor Coprocessor + Bitfield<0> PE; // Protection Enabled + EndBitUnion(CR0) + + // Page Fault Virtual Address + BitUnion64(CR2) + Bitfield<31, 0> legacy; + EndBitUnion(CR2) + + BitUnion64(CR3) + Bitfield<51, 12> longPDTB; // Long Mode Page-Directory-Table + // Base Address + Bitfield<31, 12> PDTB; // Non-PAE Addressing Page-Directory-Table + // Base Address + Bitfield<31, 5> PAEPDTB; // PAE Addressing Page-Directory-Table + // Base Address + Bitfield<4> PCD; // Page-Level Cache Disable + Bitfield<3> PWT; // Page-Level Writethrough + EndBitUnion(CR3) + + BitUnion64(CR4) + Bitfield<10> OSXMMEXCPT; // Operating System Unmasked + // Exception Support + Bitfield<9> OSFXSR; // Operating System FXSave/FSRSTOR Support + Bitfield<8> PCE; // Performance-Monitoring Counter Enable + Bitfield<7> PGE; // Page-Global Enable + Bitfield<6> MCE; // Machine Check Enable + Bitfield<5> PAE; // Physical-Address Extension + Bitfield<4> PSE; // Page Size Extensions + Bitfield<3> DE; // Debugging Extensions + Bitfield<2> TSD; // Time Stamp Disable + Bitfield<1> PVI; // Protected-Mode Virtual Interrupts + Bitfield<0> VME; // Virtual-8086 Mode Extensions + EndBitUnion(CR4) + + BitUnion64(CR8) + Bitfield<3, 0> TPR; // Task Priority Register + EndBitUnion(CR4) + + /** + * Segment Selector + */ + BitUnion64(SegSelector) + Bitfield<15, 3> SI; // Selector Index + Bitfield<2> TI; // Table Indicator + Bitfield<1, 0> RPL; // Requestor Privilege Level + EndBitUnion(SegSelector) + + /** + * Segment Descriptors + */ + + BitUnion64(SegDescriptor) + Bitfield<63, 56> baseHigh; + Bitfield<39, 16> baseLow; + Bitfield<55> G; // Granularity + Bitfield<54> D; // Default Operand Size + Bitfield<54> B; // Default Operand Size + Bitfield<53> L; // Long Attribute Bit + Bitfield<52> AVL; // Available To Software + Bitfield<51, 48> limitHigh; + Bitfield<15, 0> limitLow; + Bitfield<47> P; // Present + Bitfield<46, 45> DPL; // Descriptor Privilege-Level + Bitfield<44> S; // System + SubBitUnion(type, 43, 40) + // Specifies whether this descriptor is for code or data. + Bitfield<43> codeOrData; + + // These bit fields are for code segments + Bitfield<42> C; // Conforming + Bitfield<41> R; // Readable + + // These bit fields are for data segments + Bitfield<42> E; // Expand-Down + Bitfield<41> W; // Writable + + // This is used for both code and data segments. + Bitfield<40> A; // Accessed + EndSubBitUnion(type) + EndBitUnion(SegDescriptor) + + BitUnion64(GateDescriptor) + Bitfield<63, 48> offsetHigh; // Target Code-Segment Offset + Bitfield<15, 0> offsetLow; // Target Code-Segment Offset + Bitfield<31, 16> selector; // Target Code-Segment Selector + Bitfield<47> P; // Present + Bitfield<46, 45> DPL; // Descriptor Privilege-Level + Bitfield<43, 40> type; + Bitfield<36, 32> count; // Parameter Count + EndBitUnion(GateDescriptor) + + /** + * Descriptor-Table Registers + */ + BitUnion64(GDTR) + EndBitUnion(GDTR) + + BitUnion64(IDTR) + EndBitUnion(IDTR) + + BitUnion64(LDTR) + EndBitUnion(LDTR) + + /** + * Task Register + */ + BitUnion64(TR) + EndBitUnion(TR) +}; + +#endif // __ARCH_X86_INTREGS_HH__ diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index 49f76699b..295ca10a4 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -72,7 +72,6 @@ namespace X86ISA immediateCollected = 0; emi.immediate = 0; - displacementCollected = 0; emi.displacement = 0; emi.modRM = 0; @@ -235,14 +234,42 @@ namespace X86ISA logOpSize = 1; // 16 bit operand size } + //Set the actual op size + emi.opSize = 1 << logOpSize; + + //Figure out the effective address size. This can be overriden to + //a fixed value at the decoder level. + int logAddrSize; + if(/*FIXME 64-bit mode*/1) + { + if(emi.legacy.addr) + logAddrSize = 2; // 32 bit address size + else + logAddrSize = 3; // 64 bit address size + } + else if(/*FIXME default 32*/1) + { + if(emi.legacy.addr) + logAddrSize = 1; // 16 bit address size + else + logAddrSize = 2; // 32 bit address size + } + else // 16 bit default operand size + { + if(emi.legacy.addr) + logAddrSize = 2; // 32 bit address size + else + logAddrSize = 1; // 16 bit address size + } + + //Set the actual address size + emi.addrSize = 1 << logAddrSize; + //Figure out how big of an immediate we'll retreive based //on the opcode. int immType = ImmediateType[emi.opcode.num - 1][nextByte]; immediateSize = SizeTypeToSize[logOpSize - 1][immType]; - //Set the actual op size - emi.opSize = 1 << logOpSize; - //Determine what to expect next if (UsesModRM[emi.opcode.num - 1][nextByte]) { nextState = ModRMState; @@ -277,8 +304,7 @@ namespace X86ISA displacementSize = 0; } else { //figure out 32/64 bit displacement size - if(modRM.mod == 0 && (modRM.rm == 4 || modRM.rm == 5) - || modRM.mod == 2) + if(modRM.mod == 0 && modRM.rm == 5 || modRM.mod == 2) displacementSize = 4; else if(modRM.mod == 1) displacementSize = 1; @@ -313,6 +339,8 @@ namespace X86ISA emi.sib = nextByte; DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte); consumeByte(); + if(emi.modRM.mod == 0 && emi.sib.base == 5) + displacementSize = 4; if(displacementSize) { nextState = DisplacementState; } else if(immediateSize) { @@ -330,14 +358,16 @@ namespace X86ISA { State nextState = ErrorState; - getImmediate(displacementCollected, + getImmediate(immediateCollected, emi.displacement, displacementSize); DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n", - displacementSize, displacementCollected); + displacementSize, immediateCollected); - if(displacementSize == displacementCollected) { + if(displacementSize == immediateCollected) { + //Reset this for other immediates. + immediateCollected = 0; //Sign extend the displacement switch(displacementSize) { @@ -382,6 +412,9 @@ namespace X86ISA if(immediateSize == immediateCollected) { + //Reset this for other immediates. + immediateCollected = 0; + //XXX Warning! The following is an observed pattern and might //not always be true! diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh index f34b66364..450ebd79b 100644 --- a/src/arch/x86/predecoder.hh +++ b/src/arch/x86/predecoder.hh @@ -106,13 +106,13 @@ namespace X86ISA toGet = toGet > remaining ? remaining : toGet; //Shift the bytes we want to be all the way to the right - uint64_t partialDisp = fetchChunk >> (offset * 8); + uint64_t partialImm = fetchChunk >> (offset * 8); //Mask off what we don't want - partialDisp &= mask(toGet * 8); + partialImm &= mask(toGet * 8); //Shift it over to overlay with our displacement. - partialDisp <<= (displacementCollected * 8); + partialImm <<= (immediateCollected * 8); //Put it into our displacement - current |= partialDisp; + current |= partialImm; //Update how many bytes we've collected. collected += toGet; consumeBytes(toGet); @@ -144,9 +144,10 @@ namespace X86ISA bool emiIsReady; //The size of the displacement value int displacementSize; - int displacementCollected; //The size of the immediate value int immediateSize; + //This is how much of any immediate value we've gotten. This is used + //for both the actual immediate and the displacement. int immediateCollected; enum State { diff --git a/src/arch/x86/syscallreturn.hh b/src/arch/x86/syscallreturn.hh index 9f0d20e2a..6a7fdba58 100644 --- a/src/arch/x86/syscallreturn.hh +++ b/src/arch/x86/syscallreturn.hh @@ -59,16 +59,15 @@ #define __ARCH_X86_SYSCALLRETURN_HH__ #include "base/misc.hh" +#include "cpu/thread_context.hh" #include "sim/syscallreturn.hh" -class ThreadContext; - namespace X86ISA { static inline void setSyscallReturn(SyscallReturn return_value, ThreadContext * tc) { - panic("setSyscallReturn not implemented!\n"); + tc->setIntReg(INTREG_RAX, return_value.value()); } }; diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index 61ab2bac9..a509ff57a 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -61,7 +61,7 @@ #include <inttypes.h> #include <iostream> -#include "base/bitfield.hh" +#include "base/bitunion.hh" #include "base/cprintf.hh" namespace X86ISA @@ -86,11 +86,12 @@ namespace X86ISA }; BitUnion8(LegacyPrefixVector) + Bitfield<7, 4> decodeVal; Bitfield<7> repne; Bitfield<6> rep; Bitfield<5> lock; - Bitfield<4> addr; - Bitfield<3> op; + Bitfield<4> op; + Bitfield<3> addr; //There can be only one segment override, so they share the //first 3 bits in the legacyPrefixes bitfield. Bitfield<2,0> seg; @@ -184,8 +185,8 @@ namespace X86ISA "prefixA = %#x,\n\t\tprefixB = %#x\n\t},\n\t" "modRM = %#x,\n\tsib = %#x,\n\t" "immediate = %#x,\n\tdisplacement = %#x\n}\n", - emi.legacy, (uint8_t)emi.rex, - emi.opcode.num, emi.opcode.op, + (uint8_t)emi.legacy, (uint8_t)emi.rex, + emi.opcode.num, (uint8_t)emi.opcode.op, emi.opcode.prefixA, emi.opcode.prefixB, (uint8_t)emi.modRM, (uint8_t)emi.sib, emi.immediate, emi.displacement); diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh index e45d62f8f..5794e7079 100644 --- a/src/arch/x86/x86_traits.hh +++ b/src/arch/x86/x86_traits.hh @@ -61,6 +61,7 @@ namespace X86ISA { const int NumMicroIntRegs = 16; + const int NumPseudoIntRegs = 1; const int NumMMXRegs = 8; const int NumXMMRegs = 16; diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 70a46386e..664093fa2 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -161,273 +161,4 @@ findMsbSet(uint64_t val) { return msb; } -// The following implements the BitUnion system of defining bitfields -//on top of an underlying class. This is done through the pervasive use of -//both named and unnamed unions which all contain the same actual storage. -//Since they're unioned with each other, all of these storage locations -//overlap. This allows all of the bitfields to manipulate the same data -//without having to have access to each other. More details are provided with the -//individual components. - -//This namespace is for classes which implement the backend of the BitUnion -//stuff. Don't use any of these directly, except for the Bitfield classes in -//the *BitfieldTypes class(es). -namespace BitfieldBackend -{ - //A base class for all bitfields. It instantiates the actual storage, - //and provides getBits and setBits functions for manipulating it. The - //Data template parameter is type of the underlying storage. - template<class Data> - class BitfieldBase - { - protected: - Data __data; - - //This function returns a range of bits from the underlying storage. - //It relies on the "bits" function above. It's the user's - //responsibility to make sure that there is a properly overloaded - //version of this function for whatever type they want to overlay. - inline uint64_t - getBits(int first, int last) const - { - return bits(__data, first, last); - } - - //Similar to the above, but for settings bits with replaceBits. - inline void - setBits(int first, int last, uint64_t val) - { - replaceBits(__data, first, last, val); - } - }; - - //This class contains all the "regular" bitfield classes. It is inherited - //by all BitUnions which give them access to those types. - template<class Type> - class RegularBitfieldTypes - { - protected: - //This class implements ordinary bitfields, that is a span of bits - //who's msb is "first", and who's lsb is "last". - template<int first, int last=first> - class Bitfield : public BitfieldBase<Type> - { - public: - operator uint64_t () const - { - return this->getBits(first, last); - } - - uint64_t - operator=(const uint64_t _data) - { - this->setBits(first, last, _data); - return _data; - } - }; - - //A class which specializes the above so that it can only be read - //from. This is accomplished explicitly making sure the assignment - //operator is blocked. The conversion operator is carried through - //inheritance. This will unfortunately need to be copied into each - //bitfield type due to limitations with how templates work - template<int first, int last=first> - class BitfieldRO : public Bitfield<first, last> - { - private: - uint64_t - operator=(const uint64_t _data); - }; - - //Similar to the above, but only allows writing. - template<int first, int last=first> - class BitfieldWO : public Bitfield<first, last> - { - private: - operator uint64_t () const; - - public: - using Bitfield<first, last>::operator=; - }; - }; - - //This class contains all the "regular" bitfield classes. It is inherited - //by all BitUnions which give them access to those types. - template<class Type> - class SignedBitfieldTypes - { - protected: - //This class implements ordinary bitfields, that is a span of bits - //who's msb is "first", and who's lsb is "last". - template<int first, int last=first> - class SignedBitfield : public BitfieldBase<Type> - { - public: - operator int64_t () const - { - return sext<first - last + 1>(this->getBits(first, last)); - } - - int64_t - operator=(const int64_t _data) - { - this->setBits(first, last, _data); - return _data; - } - }; - - //A class which specializes the above so that it can only be read - //from. This is accomplished explicitly making sure the assignment - //operator is blocked. The conversion operator is carried through - //inheritance. This will unfortunately need to be copied into each - //bitfield type due to limitations with how templates work - template<int first, int last=first> - class SignedBitfieldRO : public SignedBitfield<first, last> - { - private: - int64_t - operator=(const int64_t _data); - }; - - //Similar to the above, but only allows writing. - template<int first, int last=first> - class SignedBitfieldWO : public SignedBitfield<first, last> - { - private: - operator int64_t () const; - - public: - int64_t operator=(const int64_t _data) - { - *((SignedBitfield<first, last> *)this) = _data; - return _data; - } - }; - }; - - template<class Type> - class BitfieldTypes : public RegularBitfieldTypes<Type>, - public SignedBitfieldTypes<Type> - {}; - - //When a BitUnion is set up, an underlying class is created which holds - //the actual union. This class then inherits from it, and provids the - //implementations for various operators. Setting things up this way - //prevents having to redefine these functions in every different BitUnion - //type. More operators could be implemented in the future, as the need - //arises. - template <class Type, class Base> - class BitUnionOperators : public Base - { - public: - operator Type () const - { - return Base::__data; - } - - Type - operator=(const Type & _data) - { - Base::__data = _data; - return _data; - } - - bool - operator<(const Base & base) const - { - return Base::__data < base.__data; - } - - bool - operator==(const Base & base) const - { - return Base::__data == base.__data; - } - }; -} - -//This macro is a backend for other macros that specialize it slightly. -//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and -//sticks the class which has the actual union in it, which -//BitfieldOperators above inherits from. Putting these classes in a special -//namespace ensures that there will be no collisions with other names as long -//as the BitUnion names themselves are all distinct and nothing else uses -//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself -//creates a typedef of the "type" parameter called __DataType. This allows -//the type to propagate outside of the macro itself in a controlled way. -//Finally, the base storage is defined which BitfieldOperators will refer to -//in the operators it defines. This macro is intended to be followed by -//bitfield definitions which will end up inside it's union. As explained -//above, these is overlayed the __data member in its entirety by each of the -//bitfields which are defined in the union, creating shared storage with no -//overhead. -#define __BitUnion(type, name) \ - namespace BitfieldUnderlyingClasses \ - { \ - class name; \ - } \ - class BitfieldUnderlyingClasses::name : \ - public BitfieldBackend::BitfieldTypes<type> \ - { \ - public: \ - typedef type __DataType; \ - union { \ - type __data;\ - -//This closes off the class and union started by the above macro. It is -//followed by a typedef which makes "name" refer to a BitfieldOperator -//class inheriting from the class and union just defined, which completes -//building up the type for the user. -#define EndBitUnion(name) \ - }; \ - }; \ - typedef BitfieldBackend::BitUnionOperators< \ - BitfieldUnderlyingClasses::name::__DataType, \ - BitfieldUnderlyingClasses::name> name; - -//This sets up a bitfield which has other bitfields nested inside of it. The -//__data member functions like the "underlying storage" of the top level -//BitUnion. Like everything else, it overlays with the top level storage, so -//making it a regular bitfield type makes the entire thing function as a -//regular bitfield when referred to by itself. -#define __SubBitUnion(fieldType, first, last, name) \ - class : public BitfieldBackend::BitfieldTypes<__DataType> \ - { \ - public: \ - union { \ - fieldType<first, last> __data; - -//This closes off the union created above and gives it a name. Unlike the top -//level BitUnion, we're interested in creating an object instead of a type. -//The operators are defined in the macro itself instead of a class for -//technical reasons. If someone determines a way to move them to one, please -//do so. -#define EndSubBitUnion(name) \ - }; \ - inline operator const __DataType () \ - { return __data; } \ - \ - inline const __DataType operator = (const __DataType & _data) \ - { __data = _data; } \ - } name; - -//Regular bitfields -//These define macros for read/write regular bitfield based subbitfields. -#define SubBitUnion(name, first, last) \ - __SubBitUnion(Bitfield, first, last, name) - -//Regular bitfields -//These define macros for read/write regular bitfield based subbitfields. -#define SignedSubBitUnion(name, first, last) \ - __SubBitUnion(SignedBitfield, first, last, name) - -//Use this to define an arbitrary type overlayed with bitfields. -#define BitUnion(type, name) __BitUnion(type, name) - -//Use this to define conveniently sized values overlayed with bitfields. -#define BitUnion64(name) __BitUnion(uint64_t, name) -#define BitUnion32(name) __BitUnion(uint32_t, name) -#define BitUnion16(name) __BitUnion(uint16_t, name) -#define BitUnion8(name) __BitUnion(uint8_t, name) - #endif // __BASE_BITFIELD_HH__ diff --git a/src/base/bitunion.hh b/src/base/bitunion.hh new file mode 100644 index 000000000..c02ca6155 --- /dev/null +++ b/src/base/bitunion.hh @@ -0,0 +1,313 @@ +/* + * 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 + */ + +#ifndef __BASE_BITUNION_HH__ +#define __BASE_BITUNION_HH__ + +#include <inttypes.h> +#include "base/bitfield.hh" + +// The following implements the BitUnion system of defining bitfields +//on top of an underlying class. This is done through the pervasive use of +//both named and unnamed unions which all contain the same actual storage. +//Since they're unioned with each other, all of these storage locations +//overlap. This allows all of the bitfields to manipulate the same data +//without having to have access to each other. More details are provided with +//the individual components. + +//This namespace is for classes which implement the backend of the BitUnion +//stuff. Don't use any of these directly, except for the Bitfield classes in +//the *BitfieldTypes class(es). +namespace BitfieldBackend +{ + //A base class for all bitfields. It instantiates the actual storage, + //and provides getBits and setBits functions for manipulating it. The + //Data template parameter is type of the underlying storage. + template<class Data> + class BitfieldBase + { + protected: + Data __data; + + //This function returns a range of bits from the underlying storage. + //It relies on the "bits" function above. It's the user's + //responsibility to make sure that there is a properly overloaded + //version of this function for whatever type they want to overlay. + inline uint64_t + getBits(int first, int last) const + { + return bits(__data, first, last); + } + + //Similar to the above, but for settings bits with replaceBits. + inline void + setBits(int first, int last, uint64_t val) + { + replaceBits(__data, first, last, val); + } + }; + + //This class contains all the "regular" bitfield classes. It is inherited + //by all BitUnions which give them access to those types. + template<class Type> + class RegularBitfieldTypes + { + protected: + //This class implements ordinary bitfields, that is a span of bits + //who's msb is "first", and who's lsb is "last". + template<int first, int last=first> + class Bitfield : public BitfieldBase<Type> + { + public: + operator uint64_t () const + { + return this->getBits(first, last); + } + + uint64_t + operator=(const uint64_t _data) + { + this->setBits(first, last, _data); + return _data; + } + }; + + //A class which specializes the above so that it can only be read + //from. This is accomplished explicitly making sure the assignment + //operator is blocked. The conversion operator is carried through + //inheritance. This will unfortunately need to be copied into each + //bitfield type due to limitations with how templates work + template<int first, int last=first> + class BitfieldRO : public Bitfield<first, last> + { + private: + uint64_t + operator=(const uint64_t _data); + }; + + //Similar to the above, but only allows writing. + template<int first, int last=first> + class BitfieldWO : public Bitfield<first, last> + { + private: + operator uint64_t () const; + + public: + using Bitfield<first, last>::operator=; + }; + }; + + //This class contains all the "regular" bitfield classes. It is inherited + //by all BitUnions which give them access to those types. + template<class Type> + class SignedBitfieldTypes + { + protected: + //This class implements ordinary bitfields, that is a span of bits + //who's msb is "first", and who's lsb is "last". + template<int first, int last=first> + class SignedBitfield : public BitfieldBase<Type> + { + public: + operator int64_t () const + { + return sext<first - last + 1>(this->getBits(first, last)); + } + + int64_t + operator=(const int64_t _data) + { + this->setBits(first, last, _data); + return _data; + } + }; + + //A class which specializes the above so that it can only be read + //from. This is accomplished explicitly making sure the assignment + //operator is blocked. The conversion operator is carried through + //inheritance. This will unfortunately need to be copied into each + //bitfield type due to limitations with how templates work + template<int first, int last=first> + class SignedBitfieldRO : public SignedBitfield<first, last> + { + private: + int64_t + operator=(const int64_t _data); + }; + + //Similar to the above, but only allows writing. + template<int first, int last=first> + class SignedBitfieldWO : public SignedBitfield<first, last> + { + private: + operator int64_t () const; + + public: + int64_t operator=(const int64_t _data) + { + *((SignedBitfield<first, last> *)this) = _data; + return _data; + } + }; + }; + + template<class Type> + class BitfieldTypes : public RegularBitfieldTypes<Type>, + public SignedBitfieldTypes<Type> + {}; + + //When a BitUnion is set up, an underlying class is created which holds + //the actual union. This class then inherits from it, and provids the + //implementations for various operators. Setting things up this way + //prevents having to redefine these functions in every different BitUnion + //type. More operators could be implemented in the future, as the need + //arises. + template <class Type, class Base> + class BitUnionOperators : public Base + { + public: + BitUnionOperators(Type & _data) + { + Base::__data = _data; + } + + BitUnionOperators() {} + + operator Type () const + { + return Base::__data; + } + + Type + operator=(const Type & _data) + { + Base::__data = _data; + return _data; + } + + bool + operator<(const Base & base) const + { + return Base::__data < base.__data; + } + + bool + operator==(const Base & base) const + { + return Base::__data == base.__data; + } + }; +} + +//This macro is a backend for other macros that specialize it slightly. +//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and +//sticks the class which has the actual union in it, which +//BitfieldOperators above inherits from. Putting these classes in a special +//namespace ensures that there will be no collisions with other names as long +//as the BitUnion names themselves are all distinct and nothing else uses +//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself +//creates a typedef of the "type" parameter called __DataType. This allows +//the type to propagate outside of the macro itself in a controlled way. +//Finally, the base storage is defined which BitfieldOperators will refer to +//in the operators it defines. This macro is intended to be followed by +//bitfield definitions which will end up inside it's union. As explained +//above, these is overlayed the __data member in its entirety by each of the +//bitfields which are defined in the union, creating shared storage with no +//overhead. +#define __BitUnion(type, name) \ + namespace BitfieldUnderlyingClasses \ + { \ + class name; \ + } \ + class BitfieldUnderlyingClasses::name : \ + public BitfieldBackend::BitfieldTypes<type> \ + { \ + public: \ + typedef type __DataType; \ + union { \ + type __data;\ + +//This closes off the class and union started by the above macro. It is +//followed by a typedef which makes "name" refer to a BitfieldOperator +//class inheriting from the class and union just defined, which completes +//building up the type for the user. +#define EndBitUnion(name) \ + }; \ + }; \ + typedef BitfieldBackend::BitUnionOperators< \ + BitfieldUnderlyingClasses::name::__DataType, \ + BitfieldUnderlyingClasses::name> name; + +//This sets up a bitfield which has other bitfields nested inside of it. The +//__data member functions like the "underlying storage" of the top level +//BitUnion. Like everything else, it overlays with the top level storage, so +//making it a regular bitfield type makes the entire thing function as a +//regular bitfield when referred to by itself. +#define __SubBitUnion(fieldType, first, last, name) \ + class : public BitfieldBackend::BitfieldTypes<__DataType> \ + { \ + public: \ + union { \ + fieldType<first, last> __data; + +//This closes off the union created above and gives it a name. Unlike the top +//level BitUnion, we're interested in creating an object instead of a type. +//The operators are defined in the macro itself instead of a class for +//technical reasons. If someone determines a way to move them to one, please +//do so. +#define EndSubBitUnion(name) \ + }; \ + inline operator const __DataType () \ + { return __data; } \ + \ + inline const __DataType operator = (const __DataType & _data) \ + { return __data = _data;} \ + } name; + +//Regular bitfields +//These define macros for read/write regular bitfield based subbitfields. +#define SubBitUnion(name, first, last) \ + __SubBitUnion(Bitfield, first, last, name) + +//Regular bitfields +//These define macros for read/write regular bitfield based subbitfields. +#define SignedSubBitUnion(name, first, last) \ + __SubBitUnion(SignedBitfield, first, last, name) + +//Use this to define an arbitrary type overlayed with bitfields. +#define BitUnion(type, name) __BitUnion(type, name) + +//Use this to define conveniently sized values overlayed with bitfields. +#define BitUnion64(name) __BitUnion(uint64_t, name) +#define BitUnion32(name) __BitUnion(uint32_t, name) +#define BitUnion16(name) __BitUnion(uint16_t, name) +#define BitUnion8(name) __BitUnion(uint8_t, name) + +#endif // __BASE_BITUNION_HH__ diff --git a/src/base/condcodes.hh b/src/base/condcodes.hh new file mode 100644 index 000000000..efff12dc8 --- /dev/null +++ b/src/base/condcodes.hh @@ -0,0 +1,94 @@ +/* + * 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 + */ + +#ifndef __BASE_CONDCODE_HH__ +#define __BASE_CONDCODE_HH__ + +#include "base/bitfield.hh" +#include "base/trace.hh" + +/** + * Calculate the carry flag from an addition. This should work even when + * a carry value is also added in. + */ +inline +bool +findCarry(int width, uint64_t dest, uint64_t src1, uint64_t src2) { + int shift = width - 1; + return ((~(dest >> shift) & 1) + + ((src1 >> shift) & 1) + + ((src2 >> shift) & 1)) & 0x2; +} + +/** + * Calculate the overflow flag from an addition. + */ +inline +bool +findOverflow(int width, uint64_t dest, uint64_t src1, uint64_t src2) { + int shift = width - 1; + return ((src1 ^ ~src2) & (src1 ^ dest)) & (1 << shift); +} + +/** + * Calculate the parity of a value. 1 is for odd parity and 0 is for even. + */ +inline +bool +findParity(int width, uint64_t dest) { + dest &= width; + dest ^= (dest >> 32); + dest ^= (dest >> 16); + dest ^= (dest >> 8); + dest ^= (dest >> 4); + dest ^= (dest >> 2); + dest ^= (dest >> 1); + return dest & 1; +} + +/** + * Calculate the negative flag. + */ +inline +bool +findNegative(int width, uint64_t dest) { + return bits(dest, width - 1, width - 1); +} + +/** + * Calculate the zero flag. + */ +inline +bool +findZero(int width, uint64_t dest) { + return !(dest & mask(width)); +} + +#endif // __BASE_CONDCODE_HH__ diff --git a/src/sim/faults.hh b/src/sim/faults.hh index 2f0b5af62..f2e638945 100644 --- a/src/sim/faults.hh +++ b/src/sim/faults.hh @@ -53,12 +53,12 @@ typedef Stats::Scalar<> FaultStat; class FaultBase : public RefCounted { public: - virtual FaultName name() = 0; + virtual FaultName name() const = 0; virtual void invoke(ThreadContext * tc); // template<typename T> // bool isA() {return dynamic_cast<T *>(this);} - virtual bool isMachineCheckFault() {return false;} - virtual bool isAlignmentFault() {return false;} + virtual bool isMachineCheckFault() const {return false;} + virtual bool isAlignmentFault() const {return false;} }; FaultBase * const NoFault = 0; @@ -72,7 +72,7 @@ class UnimpFault : public FaultBase : panicStr(_str) { } - FaultName name() {return "Unimplemented simulator feature";} + FaultName name() const {return "Unimplemented simulator feature";} void invoke(ThreadContext * tc); }; @@ -82,7 +82,7 @@ class PageTableFault : public FaultBase private: Addr vaddr; public: - FaultName name() {return "M5 page table fault";} + FaultName name() const {return "M5 page table fault";} PageTableFault(Addr va) : vaddr(va) {} void invoke(ThreadContext * tc); }; diff --git a/util/style.py b/util/style.py new file mode 100644 index 000000000..3824cd7f5 --- /dev/null +++ b/util/style.py @@ -0,0 +1,374 @@ +#! /usr/bin/env python +# 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: Nathan Binkert + +import re +import os +import sys + +lead = re.compile(r'^([ \t]+)') +trail = re.compile(r'([ \t]+)$') +any_control = re.compile(r'\b(if|while|for)[ \t]*[(]') +good_control = re.compile(r'\b(if|while|for) [(]') + +lang_types = { 'c' : "C", + 'h' : "C", + 'cc' : "C++", + 'hh' : "C++", + 'cxx' : "C++", + 'hxx' : "C++", + 'cpp' : "C++", + 'hpp' : "C++", + 'C' : "C++", + 'H' : "C++", + 'i' : "swig", + 'py' : "python", + 's' : "asm", + 'S' : "asm", + 'isa' : "isa" } +whitespace_types = ('C', 'C++', 'swig', 'python', 'asm', 'isa') +format_types = ( 'C', 'C++' ) + +def file_type(filename): + extension = filename.split('.') + extension = len(extension) > 1 and extension[-1] + return lang_types.get(extension, None) + +def checkwhite_line(line): + match = lead.search(line) + if match and match.group(1).find('\t') != -1: + return False + + match = trail.search(line) + if match: + return False + + return True + +def checkwhite(filename): + if file_type(filename) not in whitespace_types: + return + + try: + f = file(filename, 'r+') + except OSError, msg: + print 'could not open file %s: %s' % (filename, msg) + return + + for num,line in enumerate(f): + if not checkwhite_line(line): + yield line,num + 1 + +def fixwhite_line(line): + if lead.search(line): + newline = '' + for i,c in enumerate(line): + if c == ' ': + newline += ' ' + elif c == '\t': + newline += ' ' * (tabsize - len(newline) % tabsize) + else: + newline += line[i:] + break + + line = newline + + return line.rstrip() + '\n' + +def fixwhite(filename, tabsize, fixonly=None): + if file_type(filename) not in whitespace_types: + return + + try: + f = file(filename, 'r+') + except OSError, msg: + print 'could not open file %s: %s' % (filename, msg) + return + + lines = list(f) + + f.seek(0) + f.truncate() + + for i,line in enumerate(lines): + if fixonly is None or i in fixonly: + line = fixwhite_line(line) + + print >>f, line, + +def linelen(line): + tabs = line.count('\t') + if not tabs: + return len(line) + + count = 0 + for c in line: + if c == '\t': + count += tabsize - count % tabsize + else: + count += 1 + + return count + +class ValidationStats(object): + def __init__(self): + self.toolong = 0 + self.toolong80 = 0 + self.leadtabs = 0 + self.trailwhite = 0 + self.badcontrol = 0 + self.cret = 0 + + def dump(self): + print '''\ +%d violations of lines over 79 chars. %d of which are 80 chars exactly. +%d cases of whitespace at the end of a line. +%d cases of tabs to indent. +%d bad parens after if/while/for. +%d carriage returns found. +''' % (self.toolong, self.toolong80, self.trailwhite, self.leadtabs, + self.badcontrol, self.cret) + + def __nonzero__(self): + return self.toolong or self.toolong80 or self.leadtabs or \ + self.trailwhite or self.badcontrol or self.cret + +def validate(filename, stats, verbose, exit_code): + if file_type(filename) not in format_types: + return + + def msg(lineno, line, message): + print '%s:%d>' % (filename, lineno + 1), message + if verbose > 2: + print line + + def bad(): + if exit_code is not None: + sys.exit(exit_code) + + cpp = filename.endswith('.cc') or filename.endswith('.hh') + py = filename.endswith('.py') + + if py + cpp != 1: + raise AttributeError, \ + "I don't know how to deal with the file %s" % filename + + try: + f = file(filename, 'r') + except OSError: + if verbose > 0: + print 'could not open file %s' % filename + bad() + return + + for i,line in enumerate(f): + line = line.rstrip('\n') + + # no carriage returns + if line.find('\r') != -1: + self.cret += 1 + if verbose > 1: + msg(i, line, 'carriage return found') + bad() + + # lines max out at 79 chars + llen = linelen(line) + if llen > 79: + stats.toolong += 1 + if llen == 80: + stats.toolong80 += 1 + if verbose > 1: + msg(i, line, 'line too long (%d chars)' % llen) + bad() + + # no tabs used to indent + match = lead.search(line) + if match and match.group(1).find('\t') != -1: + stats.leadtabs += 1 + if verbose > 1: + msg(i, line, 'using tabs to indent') + bad() + + # no trailing whitespace + if trail.search(line): + stats.trailwhite +=1 + if verbose > 1: + msg(i, line, 'trailing whitespace') + bad() + + # for c++, exactly one space betwen if/while/for and ( + if cpp: + match = any_control.search(line) + if match and not good_control.search(line): + stats.badcontrol += 1 + if verbose > 1: + msg(i, line, 'improper spacing after %s' % match.group(1)) + bad() + +def check_whitespace(ui, repo, hooktype, node, parent1, parent2): + from mercurial import bdiff, mdiff, util + if hooktype != 'pretxncommit': + raise AttributeError, \ + "This hook is only meant for pretxncommit, not %s" % hooktype + + tabsize = 8 + verbose = ui.configbool('style', 'verbose', False) + def prompt(name, fixonly=None): + result = ui.prompt("(a)bort, (i)gnore, or (f)ix?", "^[aif]$", "a") + if result == 'a': + return True + elif result == 'i': + pass + elif result == 'f': + fixwhite(name, tabsize, fixonly) + else: + raise RepoError, "Invalid response: '%s'" % result + + return False + + modified, added, removed, deleted, unknown, ignore, clean = repo.status() + + for fname in added: + ok = True + for line,num in checkwhite(fname): + ui.write("invalid whitespace in %s:%d\n" % (fname, num)) + if verbose: + ui.write(">>%s<<\n" % line[-1]) + ok = False + + if not ok: + if prompt(fname): + return True + + wctx = repo.workingctx() + for fname in modified: + fctx = wctx.filectx(fname) + pctx = fctx.parents() + assert len(pctx) == 1 + + pdata = pctx[0].data() + fdata = fctx.data() + + fixonly = set() + lines = enumerate(mdiff.splitnewlines(fdata)) + for pbeg, pend, fbeg, fend in bdiff.blocks(pdata, fdata): + for i, line in lines: + if i < fbeg: + if checkwhite_line(line): + continue + + ui.write("invalid whitespace: %s:%d\n" % (fname, i+1)) + if verbose: + ui.write(">>%s<<\n" % line[:-1]) + fixonly.add(i) + elif i + 1 >= fend: + break + + if fixonly: + if prompt(fname, fixonly): + return True + +def check_format(ui, repo, hooktype, node, parent1, parent2): + if hooktype != 'pretxncommit': + raise AttributeError, \ + "This hook is only meant for pretxncommit, not %s" % hooktype + + modified, added, removed, deleted, unknown, ignore, clean = repo.status() + + verbose = 0 + stats = ValidationStats() + for f in modified + added: + validate(f, stats, verbose, None) + + if stats: + stats.dump() + result = ui.prompt("invalid formatting\n(i)gnore or (a)bort?", + "^[ia]$", "a") + if result.startswith('i'): + pass + elif result.startswith('a'): + return True + else: + raise RepoError, "Invalid response: '%s'" % result + + return False + +if __name__ == '__main__': + import getopt + + progname = sys.argv[0] + if len(sys.argv) < 2: + sys.exit('usage: %s <command> [<command args>]' % progname) + + fixwhite_usage = '%s fixwhite [-t <tabsize> ] <path> [...] \n' % progname + chkformat_usage = '%s chkformat <path> [...] \n' % progname + chkwhite_usage = '%s chkwhite <path> [...] \n' % progname + + command = sys.argv[1] + if command == 'fixwhite': + flags = 't:' + usage = fixwhite_usage + elif command == 'chkwhite': + flags = 'nv' + usage = chkwhite_usage + elif command == 'chkformat': + flags = 'nv' + usage = chkformat_usage + else: + sys.exit(fixwhite_usage + chkwhite_usage + chkformat_usage) + + opts, args = getopt.getopt(sys.argv[2:], flags) + + code = 1 + verbose = 1 + tabsize = 8 + for opt,arg in opts: + if opt == '-n': + code = None + if opt == '-t': + tabsize = int(arg) + if opt == '-v': + verbose += 1 + + if command == 'fixwhite': + for filename in args: + fixwhite(filename, tabsize) + elif command == 'chkwhite': + for filename in args: + line = checkwhite(filename) + if line: + print 'invalid whitespace at %s:%d' % (filename, line) + elif command == 'chkformat': + stats = ValidationStats() + for filename in files: + validate(filename, stats=stats, verbose=verbose, exit_code=code) + + if verbose > 0: + stats.dump() + else: + sys.exit("command '%s' not found" % command) |