19022Sgblack@eecs.umich.edu/*
29022Sgblack@eecs.umich.edu * Copyright (c) 2011 Google
39022Sgblack@eecs.umich.edu * All rights reserved.
49022Sgblack@eecs.umich.edu *
59022Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
69022Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
79022Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
89022Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
99022Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
109022Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
119022Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
129022Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
139022Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
149022Sgblack@eecs.umich.edu * this software without specific prior written permission.
159022Sgblack@eecs.umich.edu *
169022Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179022Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189022Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199022Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209022Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219022Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229022Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239022Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249022Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259022Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269022Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279022Sgblack@eecs.umich.edu *
289022Sgblack@eecs.umich.edu * Authors: Gabe Black
299022Sgblack@eecs.umich.edu */
309022Sgblack@eecs.umich.edu
319022Sgblack@eecs.umich.edu#include "arch/x86/decoder.hh"
3211793Sbrandon.potter@amd.com
339023Sgblack@eecs.umich.edu#include "arch/x86/regs/misc.hh"
3412334Sgabeblack@google.com#include "base/logging.hh"
359023Sgblack@eecs.umich.edu#include "base/trace.hh"
369023Sgblack@eecs.umich.edu#include "base/types.hh"
379023Sgblack@eecs.umich.edu#include "debug/Decoder.hh"
389022Sgblack@eecs.umich.edu
399022Sgblack@eecs.umich.edunamespace X86ISA
409022Sgblack@eecs.umich.edu{
419376Sgblack@eecs.umich.edu
429376Sgblack@eecs.umich.eduDecoder::State
439376Sgblack@eecs.umich.eduDecoder::doResetState()
449023Sgblack@eecs.umich.edu{
459023Sgblack@eecs.umich.edu    origPC = basePC + offset;
469023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Setting origPC to %#x\n", origPC);
479376Sgblack@eecs.umich.edu    instBytes = &decodePages->lookup(origPC);
489376Sgblack@eecs.umich.edu    chunkIdx = 0;
499376Sgblack@eecs.umich.edu
509023Sgblack@eecs.umich.edu    emi.rex = 0;
519023Sgblack@eecs.umich.edu    emi.legacy = 0;
5210924Snilay@cs.wisc.edu    emi.vex = 0;
5310924Snilay@cs.wisc.edu
5410593Sgabeblack@google.com    emi.opcode.type = BadOpcode;
559023Sgblack@eecs.umich.edu    emi.opcode.op = 0;
569023Sgblack@eecs.umich.edu
579023Sgblack@eecs.umich.edu    immediateCollected = 0;
589023Sgblack@eecs.umich.edu    emi.immediate = 0;
599023Sgblack@eecs.umich.edu    emi.displacement = 0;
609023Sgblack@eecs.umich.edu    emi.dispSize = 0;
619023Sgblack@eecs.umich.edu
629023Sgblack@eecs.umich.edu    emi.modRM = 0;
639023Sgblack@eecs.umich.edu    emi.sib = 0;
649376Sgblack@eecs.umich.edu
659376Sgblack@eecs.umich.edu    if (instBytes->si) {
669376Sgblack@eecs.umich.edu        return FromCacheState;
679376Sgblack@eecs.umich.edu    } else {
689376Sgblack@eecs.umich.edu        instBytes->chunks.clear();
699376Sgblack@eecs.umich.edu        return PrefixState;
709376Sgblack@eecs.umich.edu    }
719023Sgblack@eecs.umich.edu}
729023Sgblack@eecs.umich.edu
739376Sgblack@eecs.umich.eduvoid
749376Sgblack@eecs.umich.eduDecoder::process()
759023Sgblack@eecs.umich.edu{
769023Sgblack@eecs.umich.edu    //This function drives the decoder state machine.
779023Sgblack@eecs.umich.edu
789023Sgblack@eecs.umich.edu    //Some sanity checks. You shouldn't try to process more bytes if
799023Sgblack@eecs.umich.edu    //there aren't any, and you shouldn't overwrite an already
809023Sgblack@eecs.umich.edu    //decoder ExtMachInst.
819023Sgblack@eecs.umich.edu    assert(!outOfBytes);
829023Sgblack@eecs.umich.edu    assert(!instDone);
839023Sgblack@eecs.umich.edu
849376Sgblack@eecs.umich.edu    if (state == ResetState)
859376Sgblack@eecs.umich.edu        state = doResetState();
869376Sgblack@eecs.umich.edu    if (state == FromCacheState) {
879376Sgblack@eecs.umich.edu        state = doFromCacheState();
889376Sgblack@eecs.umich.edu    } else {
899376Sgblack@eecs.umich.edu        instBytes->chunks.push_back(fetchChunk);
909376Sgblack@eecs.umich.edu    }
919376Sgblack@eecs.umich.edu
929023Sgblack@eecs.umich.edu    //While there's still something to do...
939376Sgblack@eecs.umich.edu    while (!instDone && !outOfBytes) {
949023Sgblack@eecs.umich.edu        uint8_t nextByte = getNextByte();
959376Sgblack@eecs.umich.edu        switch (state) {
969023Sgblack@eecs.umich.edu          case PrefixState:
979023Sgblack@eecs.umich.edu            state = doPrefixState(nextByte);
989023Sgblack@eecs.umich.edu            break;
9912045Sgabeblack@google.com          case Vex2Of2State:
10012045Sgabeblack@google.com            state = doVex2Of2State(nextByte);
10110924Snilay@cs.wisc.edu            break;
10212045Sgabeblack@google.com          case Vex2Of3State:
10312045Sgabeblack@google.com            state = doVex2Of3State(nextByte);
10410924Snilay@cs.wisc.edu            break;
10512045Sgabeblack@google.com          case Vex3Of3State:
10612045Sgabeblack@google.com            state = doVex3Of3State(nextByte);
10710924Snilay@cs.wisc.edu            break;
10812045Sgabeblack@google.com          case VexOpcodeState:
10912045Sgabeblack@google.com            state = doVexOpcodeState(nextByte);
11012045Sgabeblack@google.com            break;
11110593Sgabeblack@google.com          case OneByteOpcodeState:
11210593Sgabeblack@google.com            state = doOneByteOpcodeState(nextByte);
11310593Sgabeblack@google.com            break;
11410593Sgabeblack@google.com          case TwoByteOpcodeState:
11510593Sgabeblack@google.com            state = doTwoByteOpcodeState(nextByte);
11610593Sgabeblack@google.com            break;
11710593Sgabeblack@google.com          case ThreeByte0F38OpcodeState:
11810593Sgabeblack@google.com            state = doThreeByte0F38OpcodeState(nextByte);
11910593Sgabeblack@google.com            break;
12010593Sgabeblack@google.com          case ThreeByte0F3AOpcodeState:
12110593Sgabeblack@google.com            state = doThreeByte0F3AOpcodeState(nextByte);
1229023Sgblack@eecs.umich.edu            break;
1239023Sgblack@eecs.umich.edu          case ModRMState:
1249023Sgblack@eecs.umich.edu            state = doModRMState(nextByte);
1259023Sgblack@eecs.umich.edu            break;
1269023Sgblack@eecs.umich.edu          case SIBState:
1279023Sgblack@eecs.umich.edu            state = doSIBState(nextByte);
1289023Sgblack@eecs.umich.edu            break;
1299023Sgblack@eecs.umich.edu          case DisplacementState:
1309023Sgblack@eecs.umich.edu            state = doDisplacementState();
1319023Sgblack@eecs.umich.edu            break;
1329023Sgblack@eecs.umich.edu          case ImmediateState:
1339023Sgblack@eecs.umich.edu            state = doImmediateState();
1349023Sgblack@eecs.umich.edu            break;
1359023Sgblack@eecs.umich.edu          case ErrorState:
1369023Sgblack@eecs.umich.edu            panic("Went to the error state in the decoder.\n");
1379023Sgblack@eecs.umich.edu          default:
1389023Sgblack@eecs.umich.edu            panic("Unrecognized state! %d\n", state);
1399023Sgblack@eecs.umich.edu        }
1409023Sgblack@eecs.umich.edu    }
1419023Sgblack@eecs.umich.edu}
1429023Sgblack@eecs.umich.edu
1439376Sgblack@eecs.umich.eduDecoder::State
1449376Sgblack@eecs.umich.eduDecoder::doFromCacheState()
1459376Sgblack@eecs.umich.edu{
1469376Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Looking at cache state.\n");
1479376Sgblack@eecs.umich.edu    if ((fetchChunk & instBytes->masks[chunkIdx]) !=
1489376Sgblack@eecs.umich.edu            instBytes->chunks[chunkIdx]) {
1499376Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Decode cache miss.\n");
1509376Sgblack@eecs.umich.edu        // The chached chunks didn't match what was fetched. Fall back to the
1519376Sgblack@eecs.umich.edu        // predecoder.
1529376Sgblack@eecs.umich.edu        instBytes->chunks[chunkIdx] = fetchChunk;
1539376Sgblack@eecs.umich.edu        instBytes->chunks.resize(chunkIdx + 1);
1549376Sgblack@eecs.umich.edu        instBytes->si = NULL;
1559376Sgblack@eecs.umich.edu        chunkIdx = 0;
1569376Sgblack@eecs.umich.edu        fetchChunk = instBytes->chunks[0];
1579376Sgblack@eecs.umich.edu        offset = origPC % sizeof(MachInst);
1589376Sgblack@eecs.umich.edu        basePC = origPC - offset;
1599376Sgblack@eecs.umich.edu        return PrefixState;
1609376Sgblack@eecs.umich.edu    } else if (chunkIdx == instBytes->chunks.size() - 1) {
1619376Sgblack@eecs.umich.edu        // We matched the cache, so use its value.
1629376Sgblack@eecs.umich.edu        instDone = true;
1639376Sgblack@eecs.umich.edu        offset = instBytes->lastOffset;
1649376Sgblack@eecs.umich.edu        if (offset == sizeof(MachInst))
1659376Sgblack@eecs.umich.edu            outOfBytes = true;
1669376Sgblack@eecs.umich.edu        return ResetState;
1679376Sgblack@eecs.umich.edu    } else {
1689376Sgblack@eecs.umich.edu        // We matched so far, but need to check more chunks.
1699376Sgblack@eecs.umich.edu        chunkIdx++;
1709376Sgblack@eecs.umich.edu        outOfBytes = true;
1719376Sgblack@eecs.umich.edu        return FromCacheState;
1729376Sgblack@eecs.umich.edu    }
1739376Sgblack@eecs.umich.edu}
1749376Sgblack@eecs.umich.edu
1759023Sgblack@eecs.umich.edu//Either get a prefix and record it in the ExtMachInst, or send the
1769023Sgblack@eecs.umich.edu//state machine on to get the opcode(s).
1779376Sgblack@eecs.umich.eduDecoder::State
1789376Sgblack@eecs.umich.eduDecoder::doPrefixState(uint8_t nextByte)
1799023Sgblack@eecs.umich.edu{
1809023Sgblack@eecs.umich.edu    uint8_t prefix = Prefixes[nextByte];
1819023Sgblack@eecs.umich.edu    State nextState = PrefixState;
1829023Sgblack@eecs.umich.edu    // REX prefixes are only recognized in 64 bit mode.
1839023Sgblack@eecs.umich.edu    if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode)
1849023Sgblack@eecs.umich.edu        prefix = 0;
1859023Sgblack@eecs.umich.edu    if (prefix)
1869023Sgblack@eecs.umich.edu        consumeByte();
1879023Sgblack@eecs.umich.edu    switch(prefix)
1889023Sgblack@eecs.umich.edu    {
1899023Sgblack@eecs.umich.edu        //Operand size override prefixes
1909023Sgblack@eecs.umich.edu      case OperandSizeOverride:
1919023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Found operand size override prefix.\n");
1929023Sgblack@eecs.umich.edu        emi.legacy.op = true;
1939023Sgblack@eecs.umich.edu        break;
1949023Sgblack@eecs.umich.edu      case AddressSizeOverride:
1959023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Found address size override prefix.\n");
1969023Sgblack@eecs.umich.edu        emi.legacy.addr = true;
1979023Sgblack@eecs.umich.edu        break;
1989023Sgblack@eecs.umich.edu        //Segment override prefixes
1999023Sgblack@eecs.umich.edu      case CSOverride:
2009023Sgblack@eecs.umich.edu      case DSOverride:
2019023Sgblack@eecs.umich.edu      case ESOverride:
2029023Sgblack@eecs.umich.edu      case FSOverride:
2039023Sgblack@eecs.umich.edu      case GSOverride:
2049023Sgblack@eecs.umich.edu      case SSOverride:
2059023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Found segment override.\n");
2069023Sgblack@eecs.umich.edu        emi.legacy.seg = prefix;
2079023Sgblack@eecs.umich.edu        break;
2089023Sgblack@eecs.umich.edu      case Lock:
2099023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Found lock prefix.\n");
2109023Sgblack@eecs.umich.edu        emi.legacy.lock = true;
2119023Sgblack@eecs.umich.edu        break;
2129023Sgblack@eecs.umich.edu      case Rep:
2139023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Found rep prefix.\n");
2149023Sgblack@eecs.umich.edu        emi.legacy.rep = true;
2159023Sgblack@eecs.umich.edu        break;
2169023Sgblack@eecs.umich.edu      case Repne:
2179023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Found repne prefix.\n");
2189023Sgblack@eecs.umich.edu        emi.legacy.repne = true;
2199023Sgblack@eecs.umich.edu        break;
2209023Sgblack@eecs.umich.edu      case RexPrefix:
2219023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Found Rex prefix %#x.\n", nextByte);
2229023Sgblack@eecs.umich.edu        emi.rex = nextByte;
2239023Sgblack@eecs.umich.edu        break;
22410924Snilay@cs.wisc.edu      case Vex2Prefix:
22510924Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found VEX two-byte prefix %#x.\n", nextByte);
22612045Sgabeblack@google.com        emi.vex.present = 1;
22712045Sgabeblack@google.com        nextState = Vex2Of2State;
22810924Snilay@cs.wisc.edu        break;
22910924Snilay@cs.wisc.edu      case Vex3Prefix:
23010924Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found VEX three-byte prefix %#x.\n", nextByte);
23112045Sgabeblack@google.com        emi.vex.present = 1;
23212045Sgabeblack@google.com        nextState = Vex2Of3State;
23310924Snilay@cs.wisc.edu        break;
2349023Sgblack@eecs.umich.edu      case 0:
23510593Sgabeblack@google.com        nextState = OneByteOpcodeState;
2369023Sgblack@eecs.umich.edu        break;
23710924Snilay@cs.wisc.edu
2389023Sgblack@eecs.umich.edu      default:
2399023Sgblack@eecs.umich.edu        panic("Unrecognized prefix %#x\n", nextByte);
2409023Sgblack@eecs.umich.edu    }
2419023Sgblack@eecs.umich.edu    return nextState;
2429023Sgblack@eecs.umich.edu}
2439023Sgblack@eecs.umich.edu
24410924Snilay@cs.wisc.eduDecoder::State
24512045Sgabeblack@google.comDecoder::doVex2Of2State(uint8_t nextByte)
24610924Snilay@cs.wisc.edu{
24710924Snilay@cs.wisc.edu    consumeByte();
24812045Sgabeblack@google.com    Vex2Of2 vex = nextByte;
24910924Snilay@cs.wisc.edu
25012045Sgabeblack@google.com    emi.rex.r = !vex.r;
25110924Snilay@cs.wisc.edu
25212045Sgabeblack@google.com    emi.vex.l = vex.l;
25312045Sgabeblack@google.com    emi.vex.v = ~vex.v;
25410924Snilay@cs.wisc.edu
25512045Sgabeblack@google.com    switch (vex.p) {
25612045Sgabeblack@google.com      case 0:
25712045Sgabeblack@google.com        break;
25812045Sgabeblack@google.com      case 1:
25912045Sgabeblack@google.com        emi.legacy.op = 1;
26012045Sgabeblack@google.com        break;
26112045Sgabeblack@google.com      case 2:
26212045Sgabeblack@google.com        emi.legacy.rep = 1;
26312045Sgabeblack@google.com        break;
26412045Sgabeblack@google.com      case 3:
26512045Sgabeblack@google.com        emi.legacy.repne = 1;
26612045Sgabeblack@google.com        break;
26712045Sgabeblack@google.com    }
26812045Sgabeblack@google.com
26912045Sgabeblack@google.com    emi.opcode.type = TwoByteOpcode;
27012045Sgabeblack@google.com
27112045Sgabeblack@google.com    return VexOpcodeState;
27210924Snilay@cs.wisc.edu}
27310924Snilay@cs.wisc.edu
27410924Snilay@cs.wisc.eduDecoder::State
27512045Sgabeblack@google.comDecoder::doVex2Of3State(uint8_t nextByte)
27610924Snilay@cs.wisc.edu{
27712045Sgabeblack@google.com    if (emi.mode.submode != SixtyFourBitMode && bits(nextByte, 7, 6) == 0x3) {
27812045Sgabeblack@google.com        // This was actually an LDS instruction. Reroute to that path.
27912045Sgabeblack@google.com        emi.vex.present = 0;
28012045Sgabeblack@google.com        emi.opcode.type = OneByteOpcode;
28112045Sgabeblack@google.com        emi.opcode.op = 0xC4;
28212045Sgabeblack@google.com        return processOpcode(ImmediateTypeOneByte, UsesModRMOneByte,
28312045Sgabeblack@google.com                             nextByte >= 0xA0 && nextByte <= 0xA3);
28412045Sgabeblack@google.com    }
28512045Sgabeblack@google.com
28610924Snilay@cs.wisc.edu    consumeByte();
28712045Sgabeblack@google.com    Vex2Of3 vex = nextByte;
28812045Sgabeblack@google.com
28912045Sgabeblack@google.com    emi.rex.r = !vex.r;
29012045Sgabeblack@google.com    emi.rex.x = !vex.x;
29112045Sgabeblack@google.com    emi.rex.b = !vex.b;
29212045Sgabeblack@google.com
29312045Sgabeblack@google.com    switch (vex.m) {
29412045Sgabeblack@google.com      case 1:
29512045Sgabeblack@google.com        emi.opcode.type = TwoByteOpcode;
29612045Sgabeblack@google.com        break;
29712045Sgabeblack@google.com      case 2:
29812045Sgabeblack@google.com        emi.opcode.type = ThreeByte0F38Opcode;
29912045Sgabeblack@google.com        break;
30012045Sgabeblack@google.com      case 3:
30112045Sgabeblack@google.com        emi.opcode.type = ThreeByte0F3AOpcode;
30212045Sgabeblack@google.com        break;
30312045Sgabeblack@google.com      default:
30412045Sgabeblack@google.com        // These encodings are reserved. Pretend this was an undefined
30512045Sgabeblack@google.com        // instruction so the main decoder will behave correctly, and stop
30612045Sgabeblack@google.com        // trying to interpret bytes.
30712045Sgabeblack@google.com        emi.opcode.type = TwoByteOpcode;
30812045Sgabeblack@google.com        emi.opcode.op = 0x0B;
30912045Sgabeblack@google.com        instDone = true;
31012045Sgabeblack@google.com        return ResetState;
31112045Sgabeblack@google.com    }
31212045Sgabeblack@google.com    return Vex3Of3State;
31310924Snilay@cs.wisc.edu}
31410924Snilay@cs.wisc.edu
31510924Snilay@cs.wisc.eduDecoder::State
31612045Sgabeblack@google.comDecoder::doVex3Of3State(uint8_t nextByte)
31710924Snilay@cs.wisc.edu{
31812045Sgabeblack@google.com    if (emi.mode.submode != SixtyFourBitMode && bits(nextByte, 7, 6) == 0x3) {
31912045Sgabeblack@google.com        // This was actually an LES instruction. Reroute to that path.
32012045Sgabeblack@google.com        emi.vex.present = 0;
32112045Sgabeblack@google.com        emi.opcode.type = OneByteOpcode;
32212045Sgabeblack@google.com        emi.opcode.op = 0xC5;
32312045Sgabeblack@google.com        return processOpcode(ImmediateTypeOneByte, UsesModRMOneByte,
32412045Sgabeblack@google.com                             nextByte >= 0xA0 && nextByte <= 0xA3);
32512045Sgabeblack@google.com    }
32612045Sgabeblack@google.com
32710924Snilay@cs.wisc.edu    consumeByte();
32812045Sgabeblack@google.com    Vex3Of3 vex = nextByte;
32912045Sgabeblack@google.com
33012045Sgabeblack@google.com    emi.rex.w = vex.w;
33112045Sgabeblack@google.com
33212045Sgabeblack@google.com    emi.vex.l = vex.l;
33312045Sgabeblack@google.com    emi.vex.v = ~vex.v;
33412045Sgabeblack@google.com
33512045Sgabeblack@google.com    switch (vex.p) {
33612045Sgabeblack@google.com      case 0:
33712045Sgabeblack@google.com        break;
33812045Sgabeblack@google.com      case 1:
33912045Sgabeblack@google.com        emi.legacy.op = 1;
34012045Sgabeblack@google.com        break;
34112045Sgabeblack@google.com      case 2:
34212045Sgabeblack@google.com        emi.legacy.rep = 1;
34312045Sgabeblack@google.com        break;
34412045Sgabeblack@google.com      case 3:
34512045Sgabeblack@google.com        emi.legacy.repne = 1;
34612045Sgabeblack@google.com        break;
34712045Sgabeblack@google.com    }
34812045Sgabeblack@google.com
34912045Sgabeblack@google.com    return VexOpcodeState;
35012045Sgabeblack@google.com}
35112045Sgabeblack@google.com
35212045Sgabeblack@google.comDecoder::State
35312045Sgabeblack@google.comDecoder::doVexOpcodeState(uint8_t nextByte)
35412045Sgabeblack@google.com{
35512045Sgabeblack@google.com    DPRINTF(Decoder, "Found VEX opcode %#x.\n", nextByte);
35612045Sgabeblack@google.com
35712045Sgabeblack@google.com    emi.opcode.op = nextByte;
35812229Sgabeblack@google.com    consumeByte();
35912045Sgabeblack@google.com
36012045Sgabeblack@google.com    switch (emi.opcode.type) {
36112045Sgabeblack@google.com      case TwoByteOpcode:
36212045Sgabeblack@google.com        return processOpcode(ImmediateTypeTwoByte, UsesModRMTwoByte);
36312045Sgabeblack@google.com      case ThreeByte0F38Opcode:
36412045Sgabeblack@google.com        return processOpcode(ImmediateTypeThreeByte0F38,
36512045Sgabeblack@google.com                             UsesModRMThreeByte0F38);
36612045Sgabeblack@google.com      case ThreeByte0F3AOpcode:
36712045Sgabeblack@google.com        return processOpcode(ImmediateTypeThreeByte0F3A,
36812045Sgabeblack@google.com                             UsesModRMThreeByte0F3A);
36912045Sgabeblack@google.com      default:
37012045Sgabeblack@google.com        panic("Unrecognized opcode type %d.\n", emi.opcode.type);
37112045Sgabeblack@google.com    }
37210924Snilay@cs.wisc.edu}
37310924Snilay@cs.wisc.edu
37410593Sgabeblack@google.com// Load the first opcode byte. Determine if there are more opcode bytes, and
37510593Sgabeblack@google.com// if not, what immediate and/or ModRM is needed.
3769376Sgblack@eecs.umich.eduDecoder::State
37710593Sgabeblack@google.comDecoder::doOneByteOpcodeState(uint8_t nextByte)
3789023Sgblack@eecs.umich.edu{
3799023Sgblack@eecs.umich.edu    State nextState = ErrorState;
3809023Sgblack@eecs.umich.edu    consumeByte();
38110924Snilay@cs.wisc.edu
38212045Sgabeblack@google.com    if (nextByte == 0x0f) {
38312045Sgabeblack@google.com        DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
38410593Sgabeblack@google.com        nextState = TwoByteOpcodeState;
38510593Sgabeblack@google.com    } else {
38610593Sgabeblack@google.com        DPRINTF(Decoder, "Found one byte opcode %#x.\n", nextByte);
38710593Sgabeblack@google.com        emi.opcode.type = OneByteOpcode;
3889023Sgblack@eecs.umich.edu        emi.opcode.op = nextByte;
3899023Sgblack@eecs.umich.edu
39010593Sgabeblack@google.com        nextState = processOpcode(ImmediateTypeOneByte, UsesModRMOneByte,
39110593Sgabeblack@google.com                                  nextByte >= 0xA0 && nextByte <= 0xA3);
39210593Sgabeblack@google.com    }
39310593Sgabeblack@google.com    return nextState;
39410593Sgabeblack@google.com}
3959023Sgblack@eecs.umich.edu
39610593Sgabeblack@google.com// Load the second opcode byte. Determine if there are more opcode bytes, and
39710593Sgabeblack@google.com// if not, what immediate and/or ModRM is needed.
39810593Sgabeblack@google.comDecoder::State
39910593Sgabeblack@google.comDecoder::doTwoByteOpcodeState(uint8_t nextByte)
40010593Sgabeblack@google.com{
40110593Sgabeblack@google.com    State nextState = ErrorState;
40210593Sgabeblack@google.com    consumeByte();
40310593Sgabeblack@google.com    if (nextByte == 0x38) {
40410593Sgabeblack@google.com        nextState = ThreeByte0F38OpcodeState;
40510593Sgabeblack@google.com        DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
40610593Sgabeblack@google.com    } else if (nextByte == 0x3a) {
40710593Sgabeblack@google.com        nextState = ThreeByte0F3AOpcodeState;
40810593Sgabeblack@google.com        DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
40910593Sgabeblack@google.com    } else {
41010593Sgabeblack@google.com        DPRINTF(Decoder, "Found two byte opcode %#x.\n", nextByte);
41110593Sgabeblack@google.com        emi.opcode.type = TwoByteOpcode;
41210593Sgabeblack@google.com        emi.opcode.op = nextByte;
4139023Sgblack@eecs.umich.edu
41410593Sgabeblack@google.com        nextState = processOpcode(ImmediateTypeTwoByte, UsesModRMTwoByte);
41510593Sgabeblack@google.com    }
41610593Sgabeblack@google.com    return nextState;
41710593Sgabeblack@google.com}
4189023Sgblack@eecs.umich.edu
41910593Sgabeblack@google.com// Load the third opcode byte and determine what immediate and/or ModRM is
42010593Sgabeblack@google.com// needed.
42110593Sgabeblack@google.comDecoder::State
42210593Sgabeblack@google.comDecoder::doThreeByte0F38OpcodeState(uint8_t nextByte)
42310593Sgabeblack@google.com{
42410593Sgabeblack@google.com    consumeByte();
4259023Sgblack@eecs.umich.edu
42610593Sgabeblack@google.com    DPRINTF(Decoder, "Found three byte 0F38 opcode %#x.\n", nextByte);
42710593Sgabeblack@google.com    emi.opcode.type = ThreeByte0F38Opcode;
42810593Sgabeblack@google.com    emi.opcode.op = nextByte;
4299023Sgblack@eecs.umich.edu
43010593Sgabeblack@google.com    return processOpcode(ImmediateTypeThreeByte0F38, UsesModRMThreeByte0F38);
43110593Sgabeblack@google.com}
4329023Sgblack@eecs.umich.edu
43310593Sgabeblack@google.com// Load the third opcode byte and determine what immediate and/or ModRM is
43410593Sgabeblack@google.com// needed.
43510593Sgabeblack@google.comDecoder::State
43610593Sgabeblack@google.comDecoder::doThreeByte0F3AOpcodeState(uint8_t nextByte)
43710593Sgabeblack@google.com{
43810593Sgabeblack@google.com    consumeByte();
43910593Sgabeblack@google.com
44010593Sgabeblack@google.com    DPRINTF(Decoder, "Found three byte 0F3A opcode %#x.\n", nextByte);
44110593Sgabeblack@google.com    emi.opcode.type = ThreeByte0F3AOpcode;
44210593Sgabeblack@google.com    emi.opcode.op = nextByte;
44310593Sgabeblack@google.com
44410593Sgabeblack@google.com    return processOpcode(ImmediateTypeThreeByte0F3A, UsesModRMThreeByte0F3A);
44510593Sgabeblack@google.com}
44610593Sgabeblack@google.com
44710593Sgabeblack@google.com// Generic opcode processing which determines the immediate size, and whether
44810593Sgabeblack@google.com// or not there's a modrm byte.
44910593Sgabeblack@google.comDecoder::State
45010593Sgabeblack@google.comDecoder::processOpcode(ByteTable &immTable, ByteTable &modrmTable,
45110593Sgabeblack@google.com                       bool addrSizedImm)
45210593Sgabeblack@google.com{
45310593Sgabeblack@google.com    State nextState = ErrorState;
45410593Sgabeblack@google.com    const uint8_t opcode = emi.opcode.op;
45510593Sgabeblack@google.com
45610593Sgabeblack@google.com    //Figure out the effective operand size. This can be overriden to
45710593Sgabeblack@google.com    //a fixed value at the decoder level.
45810593Sgabeblack@google.com    int logOpSize;
45910593Sgabeblack@google.com    if (emi.rex.w)
46010593Sgabeblack@google.com        logOpSize = 3; // 64 bit operand size
46110593Sgabeblack@google.com    else if (emi.legacy.op)
46210593Sgabeblack@google.com        logOpSize = altOp;
46310593Sgabeblack@google.com    else
46410593Sgabeblack@google.com        logOpSize = defOp;
46510593Sgabeblack@google.com
46610593Sgabeblack@google.com    //Set the actual op size
46710593Sgabeblack@google.com    emi.opSize = 1 << logOpSize;
46810593Sgabeblack@google.com
46910593Sgabeblack@google.com    //Figure out the effective address size. This can be overriden to
47010593Sgabeblack@google.com    //a fixed value at the decoder level.
47110593Sgabeblack@google.com    int logAddrSize;
47211321Ssteve.reinhardt@amd.com    if (emi.legacy.addr)
47310593Sgabeblack@google.com        logAddrSize = altAddr;
47410593Sgabeblack@google.com    else
47510593Sgabeblack@google.com        logAddrSize = defAddr;
47610593Sgabeblack@google.com
47710593Sgabeblack@google.com    //Set the actual address size
47810593Sgabeblack@google.com    emi.addrSize = 1 << logAddrSize;
47910593Sgabeblack@google.com
48010593Sgabeblack@google.com    //Figure out the effective stack width. This can be overriden to
48110593Sgabeblack@google.com    //a fixed value at the decoder level.
48210593Sgabeblack@google.com    emi.stackSize = 1 << stack;
48310593Sgabeblack@google.com
48410593Sgabeblack@google.com    //Figure out how big of an immediate we'll retreive based
48510593Sgabeblack@google.com    //on the opcode.
48610593Sgabeblack@google.com    int immType = immTable[opcode];
48710593Sgabeblack@google.com    if (addrSizedImm)
48810593Sgabeblack@google.com        immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
48910593Sgabeblack@google.com    else
49010593Sgabeblack@google.com        immediateSize = SizeTypeToSize[logOpSize - 1][immType];
49110593Sgabeblack@google.com
49210593Sgabeblack@google.com    //Determine what to expect next
49310593Sgabeblack@google.com    if (modrmTable[opcode]) {
49410593Sgabeblack@google.com        nextState = ModRMState;
49510593Sgabeblack@google.com    } else {
49611321Ssteve.reinhardt@amd.com        if (immediateSize) {
49710593Sgabeblack@google.com            nextState = ImmediateState;
4989023Sgblack@eecs.umich.edu        } else {
49910593Sgabeblack@google.com            instDone = true;
50010593Sgabeblack@google.com            nextState = ResetState;
5019023Sgblack@eecs.umich.edu        }
5029023Sgblack@eecs.umich.edu    }
5039023Sgblack@eecs.umich.edu    return nextState;
5049023Sgblack@eecs.umich.edu}
5059023Sgblack@eecs.umich.edu
5069023Sgblack@eecs.umich.edu//Get the ModRM byte and determine what displacement, if any, there is.
5079023Sgblack@eecs.umich.edu//Also determine whether or not to get the SIB byte, displacement, or
5089023Sgblack@eecs.umich.edu//immediate next.
5099376Sgblack@eecs.umich.eduDecoder::State
5109376Sgblack@eecs.umich.eduDecoder::doModRMState(uint8_t nextByte)
5119023Sgblack@eecs.umich.edu{
5129023Sgblack@eecs.umich.edu    State nextState = ErrorState;
51310924Snilay@cs.wisc.edu    ModRM modRM = nextByte;
5149023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte);
5159376Sgblack@eecs.umich.edu    if (defOp == 1) {
5169023Sgblack@eecs.umich.edu        //figure out 16 bit displacement size
5179023Sgblack@eecs.umich.edu        if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
5189023Sgblack@eecs.umich.edu            displacementSize = 2;
5199023Sgblack@eecs.umich.edu        else if (modRM.mod == 1)
5209023Sgblack@eecs.umich.edu            displacementSize = 1;
5219023Sgblack@eecs.umich.edu        else
5229023Sgblack@eecs.umich.edu            displacementSize = 0;
5239023Sgblack@eecs.umich.edu    } else {
5249023Sgblack@eecs.umich.edu        //figure out 32/64 bit displacement size
5259023Sgblack@eecs.umich.edu        if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
5269023Sgblack@eecs.umich.edu            displacementSize = 4;
5279023Sgblack@eecs.umich.edu        else if (modRM.mod == 1)
5289023Sgblack@eecs.umich.edu            displacementSize = 1;
5299023Sgblack@eecs.umich.edu        else
5309023Sgblack@eecs.umich.edu            displacementSize = 0;
5319023Sgblack@eecs.umich.edu    }
5329023Sgblack@eecs.umich.edu
5339023Sgblack@eecs.umich.edu    // The "test" instruction in group 3 needs an immediate, even though
5349023Sgblack@eecs.umich.edu    // the other instructions with the same actual opcode don't.
53510593Sgabeblack@google.com    if (emi.opcode.type == OneByteOpcode && (modRM.reg & 0x6) == 0) {
5369023Sgblack@eecs.umich.edu       if (emi.opcode.op == 0xF6)
5379023Sgblack@eecs.umich.edu           immediateSize = 1;
5389023Sgblack@eecs.umich.edu       else if (emi.opcode.op == 0xF7)
5399023Sgblack@eecs.umich.edu           immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
5409023Sgblack@eecs.umich.edu    }
5419023Sgblack@eecs.umich.edu
5429023Sgblack@eecs.umich.edu    //If there's an SIB, get that next.
5439023Sgblack@eecs.umich.edu    //There is no SIB in 16 bit mode.
5449023Sgblack@eecs.umich.edu    if (modRM.rm == 4 && modRM.mod != 3) {
5459023Sgblack@eecs.umich.edu            // && in 32/64 bit mode)
5469023Sgblack@eecs.umich.edu        nextState = SIBState;
54711321Ssteve.reinhardt@amd.com    } else if (displacementSize) {
5489023Sgblack@eecs.umich.edu        nextState = DisplacementState;
54911321Ssteve.reinhardt@amd.com    } else if (immediateSize) {
5509023Sgblack@eecs.umich.edu        nextState = ImmediateState;
5519023Sgblack@eecs.umich.edu    } else {
5529023Sgblack@eecs.umich.edu        instDone = true;
5539023Sgblack@eecs.umich.edu        nextState = ResetState;
5549023Sgblack@eecs.umich.edu    }
5559023Sgblack@eecs.umich.edu    //The ModRM byte is consumed no matter what
5569023Sgblack@eecs.umich.edu    consumeByte();
5579023Sgblack@eecs.umich.edu    emi.modRM = modRM;
5589023Sgblack@eecs.umich.edu    return nextState;
5599023Sgblack@eecs.umich.edu}
5609023Sgblack@eecs.umich.edu
5619023Sgblack@eecs.umich.edu//Get the SIB byte. We don't do anything with it at this point, other
5629023Sgblack@eecs.umich.edu//than storing it in the ExtMachInst. Determine if we need to get a
5639023Sgblack@eecs.umich.edu//displacement or immediate next.
5649376Sgblack@eecs.umich.eduDecoder::State
5659376Sgblack@eecs.umich.eduDecoder::doSIBState(uint8_t nextByte)
5669023Sgblack@eecs.umich.edu{
5679023Sgblack@eecs.umich.edu    State nextState = ErrorState;
5689023Sgblack@eecs.umich.edu    emi.sib = nextByte;
5699023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Found SIB byte %#x.\n", nextByte);
5709023Sgblack@eecs.umich.edu    consumeByte();
5719023Sgblack@eecs.umich.edu    if (emi.modRM.mod == 0 && emi.sib.base == 5)
5729023Sgblack@eecs.umich.edu        displacementSize = 4;
5739023Sgblack@eecs.umich.edu    if (displacementSize) {
5749023Sgblack@eecs.umich.edu        nextState = DisplacementState;
57511321Ssteve.reinhardt@amd.com    } else if (immediateSize) {
5769023Sgblack@eecs.umich.edu        nextState = ImmediateState;
5779023Sgblack@eecs.umich.edu    } else {
5789023Sgblack@eecs.umich.edu        instDone = true;
5799023Sgblack@eecs.umich.edu        nextState = ResetState;
5809023Sgblack@eecs.umich.edu    }
5819023Sgblack@eecs.umich.edu    return nextState;
5829023Sgblack@eecs.umich.edu}
5839023Sgblack@eecs.umich.edu
5849023Sgblack@eecs.umich.edu//Gather up the displacement, or at least as much of it
5859023Sgblack@eecs.umich.edu//as we can get.
5869376Sgblack@eecs.umich.eduDecoder::State
5879376Sgblack@eecs.umich.eduDecoder::doDisplacementState()
5889023Sgblack@eecs.umich.edu{
5899023Sgblack@eecs.umich.edu    State nextState = ErrorState;
5909023Sgblack@eecs.umich.edu
5919023Sgblack@eecs.umich.edu    getImmediate(immediateCollected,
5929023Sgblack@eecs.umich.edu            emi.displacement,
5939023Sgblack@eecs.umich.edu            displacementSize);
5949023Sgblack@eecs.umich.edu
5959023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Collecting %d byte displacement, got %d bytes.\n",
5969023Sgblack@eecs.umich.edu            displacementSize, immediateCollected);
5979023Sgblack@eecs.umich.edu
59811321Ssteve.reinhardt@amd.com    if (displacementSize == immediateCollected) {
5999023Sgblack@eecs.umich.edu        //Reset this for other immediates.
6009023Sgblack@eecs.umich.edu        immediateCollected = 0;
6019023Sgblack@eecs.umich.edu        //Sign extend the displacement
6029023Sgblack@eecs.umich.edu        switch(displacementSize)
6039023Sgblack@eecs.umich.edu        {
6049023Sgblack@eecs.umich.edu          case 1:
6059023Sgblack@eecs.umich.edu            emi.displacement = sext<8>(emi.displacement);
6069023Sgblack@eecs.umich.edu            break;
6079023Sgblack@eecs.umich.edu          case 2:
6089023Sgblack@eecs.umich.edu            emi.displacement = sext<16>(emi.displacement);
6099023Sgblack@eecs.umich.edu            break;
6109023Sgblack@eecs.umich.edu          case 4:
6119023Sgblack@eecs.umich.edu            emi.displacement = sext<32>(emi.displacement);
6129023Sgblack@eecs.umich.edu            break;
6139023Sgblack@eecs.umich.edu          default:
6149023Sgblack@eecs.umich.edu            panic("Undefined displacement size!\n");
6159023Sgblack@eecs.umich.edu        }
6169023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Collected displacement %#x.\n",
6179023Sgblack@eecs.umich.edu                emi.displacement);
61811321Ssteve.reinhardt@amd.com        if (immediateSize) {
6199023Sgblack@eecs.umich.edu            nextState = ImmediateState;
6209023Sgblack@eecs.umich.edu        } else {
6219023Sgblack@eecs.umich.edu            instDone = true;
6229023Sgblack@eecs.umich.edu            nextState = ResetState;
6239023Sgblack@eecs.umich.edu        }
6249023Sgblack@eecs.umich.edu
6259023Sgblack@eecs.umich.edu        emi.dispSize = displacementSize;
6269023Sgblack@eecs.umich.edu    }
6279023Sgblack@eecs.umich.edu    else
6289023Sgblack@eecs.umich.edu        nextState = DisplacementState;
6299023Sgblack@eecs.umich.edu    return nextState;
6309023Sgblack@eecs.umich.edu}
6319023Sgblack@eecs.umich.edu
6329023Sgblack@eecs.umich.edu//Gather up the immediate, or at least as much of it
6339023Sgblack@eecs.umich.edu//as we can get
6349376Sgblack@eecs.umich.eduDecoder::State
6359376Sgblack@eecs.umich.eduDecoder::doImmediateState()
6369023Sgblack@eecs.umich.edu{
6379023Sgblack@eecs.umich.edu    State nextState = ErrorState;
6389023Sgblack@eecs.umich.edu
6399023Sgblack@eecs.umich.edu    getImmediate(immediateCollected,
6409023Sgblack@eecs.umich.edu            emi.immediate,
6419023Sgblack@eecs.umich.edu            immediateSize);
6429023Sgblack@eecs.umich.edu
6439023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Collecting %d byte immediate, got %d bytes.\n",
6449023Sgblack@eecs.umich.edu            immediateSize, immediateCollected);
6459023Sgblack@eecs.umich.edu
64611321Ssteve.reinhardt@amd.com    if (immediateSize == immediateCollected)
6479023Sgblack@eecs.umich.edu    {
6489023Sgblack@eecs.umich.edu        //Reset this for other immediates.
6499023Sgblack@eecs.umich.edu        immediateCollected = 0;
6509023Sgblack@eecs.umich.edu
6519023Sgblack@eecs.umich.edu        //XXX Warning! The following is an observed pattern and might
6529023Sgblack@eecs.umich.edu        //not always be true!
6539023Sgblack@eecs.umich.edu
6549023Sgblack@eecs.umich.edu        //Instructions which use 64 bit operands but 32 bit immediates
6559023Sgblack@eecs.umich.edu        //need to have the immediate sign extended to 64 bits.
6569023Sgblack@eecs.umich.edu        //Instructions which use true 64 bit immediates won't be
6579023Sgblack@eecs.umich.edu        //affected, and instructions that use true 32 bit immediates
6589023Sgblack@eecs.umich.edu        //won't notice.
6599023Sgblack@eecs.umich.edu        switch(immediateSize)
6609023Sgblack@eecs.umich.edu        {
6619023Sgblack@eecs.umich.edu          case 4:
6629023Sgblack@eecs.umich.edu            emi.immediate = sext<32>(emi.immediate);
6639023Sgblack@eecs.umich.edu            break;
6649023Sgblack@eecs.umich.edu          case 1:
6659023Sgblack@eecs.umich.edu            emi.immediate = sext<8>(emi.immediate);
6669023Sgblack@eecs.umich.edu        }
6679023Sgblack@eecs.umich.edu
6689023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Collected immediate %#x.\n",
6699023Sgblack@eecs.umich.edu                emi.immediate);
6709023Sgblack@eecs.umich.edu        instDone = true;
6719023Sgblack@eecs.umich.edu        nextState = ResetState;
6729023Sgblack@eecs.umich.edu    }
6739023Sgblack@eecs.umich.edu    else
6749023Sgblack@eecs.umich.edu        nextState = ImmediateState;
6759023Sgblack@eecs.umich.edu    return nextState;
6769023Sgblack@eecs.umich.edu}
6779022Sgblack@eecs.umich.edu
6789376Sgblack@eecs.umich.eduDecoder::InstBytes Decoder::dummy;
6799376Sgblack@eecs.umich.eduDecoder::InstCacheMap Decoder::instCacheMap;
6809024Sgblack@eecs.umich.edu
6819024Sgblack@eecs.umich.eduStaticInstPtr
6829024Sgblack@eecs.umich.eduDecoder::decode(ExtMachInst mach_inst, Addr addr)
6839024Sgblack@eecs.umich.edu{
68412621Sgabeblack@google.com    auto iter = instMap->find(mach_inst);
6859376Sgblack@eecs.umich.edu    if (iter != instMap->end())
6869376Sgblack@eecs.umich.edu        return iter->second;
6879376Sgblack@eecs.umich.edu
6889376Sgblack@eecs.umich.edu    StaticInstPtr si = decodeInst(mach_inst);
6899376Sgblack@eecs.umich.edu    (*instMap)[mach_inst] = si;
6909376Sgblack@eecs.umich.edu    return si;
6919376Sgblack@eecs.umich.edu}
6929376Sgblack@eecs.umich.edu
6939376Sgblack@eecs.umich.eduStaticInstPtr
6949376Sgblack@eecs.umich.eduDecoder::decode(PCState &nextPC)
6959376Sgblack@eecs.umich.edu{
6969376Sgblack@eecs.umich.edu    if (!instDone)
6979376Sgblack@eecs.umich.edu        return NULL;
6989376Sgblack@eecs.umich.edu    instDone = false;
6999376Sgblack@eecs.umich.edu    updateNPC(nextPC);
7009376Sgblack@eecs.umich.edu
7019376Sgblack@eecs.umich.edu    StaticInstPtr &si = instBytes->si;
7029376Sgblack@eecs.umich.edu    if (si)
7039024Sgblack@eecs.umich.edu        return si;
7049024Sgblack@eecs.umich.edu
7059376Sgblack@eecs.umich.edu    // We didn't match in the AddrMap, but we still populated an entry. Fix
7069376Sgblack@eecs.umich.edu    // up its byte masks.
7079376Sgblack@eecs.umich.edu    const int chunkSize = sizeof(MachInst);
7089376Sgblack@eecs.umich.edu
7099376Sgblack@eecs.umich.edu    instBytes->lastOffset = offset;
7109376Sgblack@eecs.umich.edu
7119376Sgblack@eecs.umich.edu    Addr firstBasePC = basePC - (instBytes->chunks.size() - 1) * chunkSize;
7129376Sgblack@eecs.umich.edu    Addr firstOffset = origPC - firstBasePC;
7139376Sgblack@eecs.umich.edu    Addr totalSize = instBytes->lastOffset - firstOffset +
7149376Sgblack@eecs.umich.edu        (instBytes->chunks.size() - 1) * chunkSize;
7159376Sgblack@eecs.umich.edu    int start = firstOffset;
7169376Sgblack@eecs.umich.edu    instBytes->masks.clear();
7179376Sgblack@eecs.umich.edu
7189376Sgblack@eecs.umich.edu    while (totalSize) {
7199376Sgblack@eecs.umich.edu        int end = start + totalSize;
7209376Sgblack@eecs.umich.edu        end = (chunkSize < end) ? chunkSize : end;
7219376Sgblack@eecs.umich.edu        int size = end - start;
7229376Sgblack@eecs.umich.edu        int idx = instBytes->masks.size();
7239376Sgblack@eecs.umich.edu
7249376Sgblack@eecs.umich.edu        MachInst maskVal = mask(size * 8) << (start * 8);
7259376Sgblack@eecs.umich.edu        assert(maskVal);
7269376Sgblack@eecs.umich.edu
7279376Sgblack@eecs.umich.edu        instBytes->masks.push_back(maskVal);
7289376Sgblack@eecs.umich.edu        instBytes->chunks[idx] &= instBytes->masks[idx];
7299376Sgblack@eecs.umich.edu        totalSize -= size;
7309376Sgblack@eecs.umich.edu        start = 0;
7319024Sgblack@eecs.umich.edu    }
7329024Sgblack@eecs.umich.edu
7339376Sgblack@eecs.umich.edu    si = decode(emi, origPC);
7349024Sgblack@eecs.umich.edu    return si;
7359024Sgblack@eecs.umich.edu}
7369022Sgblack@eecs.umich.edu
7379022Sgblack@eecs.umich.edu}
738