diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2010-06-02 12:58:00 -0500 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2010-06-02 12:58:00 -0500 |
commit | 96be7e16c15deecc167f99b0d6ba9fe81617197f (patch) | |
tree | 6551e060c640d456227b64ad028ca895c18730d0 /src | |
parent | f49cdb4f5d8c9740e5f021ad5704a4586e88f6c3 (diff) | |
download | gem5-96be7e16c15deecc167f99b0d6ba9fe81617197f.tar.xz |
ARM: Make the predecoder handle Thumb instructions.
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/SConscript | 14 | ||||
-rw-r--r-- | src/arch/arm/predecoder.hh | 98 | ||||
-rw-r--r-- | src/cpu/simple/base.cc | 2 |
3 files changed, 99 insertions, 15 deletions
diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript index 92a4193f1..c1a08aa49 100644 --- a/src/arch/arm/SConscript +++ b/src/arch/arm/SConscript @@ -1,9 +1,20 @@ # -*- mode:python -*- -# Copyright (c) 2007-2008 The Florida State University # Copyright (c) 2009 ARM Limited # All rights reserved. # +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Copyright (c) 2007-2008 The Florida State University +# 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 @@ -52,6 +63,7 @@ if env['TARGET_ISA'] == 'arm': TraceFlag('Arm') TraceFlag('Faults', "Trace Exceptions, interrupts, svc/swi") + TraceFlag('Predecoder', "Instructions returned by the predecoder") if env['FULL_SYSTEM']: Source('interrupts.cc') Source('stacktrace.cc') diff --git a/src/arch/arm/predecoder.hh b/src/arch/arm/predecoder.hh index b21b77320..2438f0378 100644 --- a/src/arch/arm/predecoder.hh +++ b/src/arch/arm/predecoder.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2010 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * Copyright (c) 2007-2008 The Florida State University * All rights reserved. @@ -47,9 +59,13 @@ namespace ArmISA ThreadContext * tc; //The extended machine instruction being generated ExtMachInst emi; + MachInst data; + bool bigThumb; + int offset; public: - Predecoder(ThreadContext * _tc) : tc(_tc) + Predecoder(ThreadContext * _tc) : + tc(_tc), data(0), bigThumb(false), offset(0) {} ThreadContext * getTC() @@ -62,20 +78,67 @@ namespace ArmISA tc = _tc; } - void process() - {} - void reset() - {} + { + bigThumb = false; + offset = 0; + emi = 0; + } + + void process() + { + if (!emi.thumb) { + emi.instBits = data; + emi.sevenAndFour = bits(data, 7) && bits(data, 4); + emi.isMisc = (bits(data, 24, 23) == 0x2 && + bits(data, 20) == 0); + DPRINTF(Predecoder, "Arm inst.\n"); + } else { + uint16_t word = (data >> (offset * 8)); + if (bigThumb) { + // A 32 bit thumb inst is half collected. + emi.instBits = emi.instBits | word; + bigThumb = false; + offset += 2; + DPRINTF(Predecoder, "Second half of 32 bit Thumb.\n"); + } else { + uint16_t highBits = word & 0xF800; + if (highBits == 0xE800 || highBits == 0xF000 || + highBits == 0xF800) { + // The start of a 32 bit thumb inst. + emi.bigThumb = 1; + if (offset == 0) { + // We've got the whole thing. + DPRINTF(Predecoder, + "All of 32 bit Thumb.\n"); + emi.instBits = (data >> 16) | (data << 16); + offset += 4; + } else { + // We only have the first half word. + DPRINTF(Predecoder, + "First half of 32 bit Thumb.\n"); + emi.instBits = (uint32_t)word << 16; + bigThumb = true; + offset += 2; + } + } else { + // A 16 bit thumb inst. + DPRINTF(Predecoder, "16 bit Thumb.\n"); + offset += 2; + emi.instBits = word; + } + } + } + } //Use this to give data to the predecoder. This should be used //when there is control flow. void moreBytes(Addr pc, Addr fetchPC, MachInst inst) { - emi = inst; - emi.thumb = (pc & (ULL(1) << PcTBitShift)); - emi.sevenAndFour = bits(inst, 7) && bits(inst, 4); - emi.isMisc = (bits(inst, 24, 23) == 0x2 && bits(inst, 20) == 0); + data = inst; + offset = (fetchPC >= pc) ? 0 : pc - fetchPC; + emi.thumb = (pc & (ULL(1) << PcTBitShift)) ? 1 : 0; + process(); } //Use this to give data to the predecoder. This should be used @@ -87,18 +150,27 @@ namespace ArmISA bool needMoreBytes() { - return true; + return sizeof(MachInst) > offset; } bool extMachInstReady() { - return true; + // The only way an instruction wouldn't be ready is if this is a + // 32 bit ARM instruction that's not 32 bit aligned. + return !bigThumb; + } + + int getInstSize() + { + return (!emi.thumb || emi.bigThumb) ? 4 : 2; } //This returns a constant reference to the ExtMachInst to avoid a copy - const ExtMachInst & getExtMachInst() + ExtMachInst getExtMachInst() { - return emi; + ExtMachInst thisEmi = emi; + emi = 0; + return thisEmi; } }; }; diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 17ba6a10b..d15b84bd6 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -410,7 +410,7 @@ BaseSimpleCPU::preExecute() //If an instruction is ready, decode it. Otherwise, we'll have to //fetch beyond the MachInst at the current pc. if (predecoder.extMachInstReady()) { -#if THE_ISA == X86_ISA +#if THE_ISA == X86_ISA || THE_ISA == ARM_ISA thread->setNextPC(thread->readPC() + predecoder.getInstSize()); #endif // X86_ISA stayAtPC = false; |