diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2012-05-26 13:44:46 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2012-05-26 13:44:46 -0700 |
commit | 0cba96ba6a5d7a4dab2a63b14149c49dfbfbb3bc (patch) | |
tree | 1e4e1372b76ed021060d560c2ee1a474f4b22ef0 /src/arch/arm/decoder.cc | |
parent | eae1e97fb002b44a9d8c46df2da1ddc1d0156ce4 (diff) | |
download | gem5-0cba96ba6a5d7a4dab2a63b14149c49dfbfbb3bc.tar.xz |
CPU: Merge the predecoder and decoder.
These classes are always used together, and merging them will give the ISAs
more flexibility in how they cache things and manage the process.
--HG--
rename : src/arch/x86/predecoder_tables.cc => src/arch/x86/decoder_tables.cc
Diffstat (limited to 'src/arch/arm/decoder.cc')
-rw-r--r-- | src/arch/arm/decoder.cc | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/src/arch/arm/decoder.cc b/src/arch/arm/decoder.cc index be46ff540..65badbc49 100644 --- a/src/arch/arm/decoder.cc +++ b/src/arch/arm/decoder.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Google + * Copyright (c) 2012 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,10 +29,96 @@ */ #include "arch/arm/decoder.hh" +#include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" +#include "base/trace.hh" +#include "cpu/thread_context.hh" +#include "debug/Decoder.hh" namespace ArmISA { DecodeCache Decoder::defaultCache; +void +Decoder::process() +{ + // emi is typically ready, with some caveats below... + instDone = true; + + 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); + consumeBytes(4); + DPRINTF(Decoder, "Arm inst: %#x.\n", (uint64_t)emi); + } else { + uint16_t word = (data >> (offset * 8)); + if (bigThumb) { + // A 32 bit thumb inst is half collected. + emi.instBits = emi.instBits | word; + bigThumb = false; + consumeBytes(2); + DPRINTF(Decoder, "Second half of 32 bit Thumb: %#x.\n", + emi.instBits); + } 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. + emi.instBits = (data >> 16) | (data << 16); + DPRINTF(Decoder, "All of 32 bit Thumb: %#x.\n", + emi.instBits); + consumeBytes(4); + } else { + // We only have the first half word. + DPRINTF(Decoder, + "First half of 32 bit Thumb.\n"); + emi.instBits = (uint32_t)word << 16; + bigThumb = true; + consumeBytes(2); + // emi not ready yet. + instDone = false; + } + } else { + // A 16 bit thumb inst. + consumeBytes(2); + emi.instBits = word; + // Set the condition code field artificially. + emi.condCode = COND_UC; + DPRINTF(Decoder, "16 bit Thumb: %#x.\n", + emi.instBits); + if (bits(word, 15, 8) == 0xbf && + bits(word, 3, 0) != 0x0) { + foundIt = true; + itBits = bits(word, 7, 0); + DPRINTF(Decoder, + "IT detected, cond = %#x, mask = %#x\n", + itBits.cond, itBits.mask); + } + } + } + } +} + +//Use this to give data to the decoder. This should be used +//when there is control flow. +void +Decoder::moreBytes(const PCState &pc, Addr fetchPC, MachInst inst) +{ + data = inst; + offset = (fetchPC >= pc.instAddr()) ? 0 : pc.instAddr() - fetchPC; + emi.thumb = pc.thumb(); + FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR); + emi.fpscrLen = fpscr.len; + emi.fpscrStride = fpscr.stride; + + outOfBytes = false; + process(); +} + } |