decoder.cc revision 10924
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"
329023Sgblack@eecs.umich.edu#include "arch/x86/regs/misc.hh"
339023Sgblack@eecs.umich.edu#include "base/misc.hh"
349023Sgblack@eecs.umich.edu#include "base/trace.hh"
359023Sgblack@eecs.umich.edu#include "base/types.hh"
369023Sgblack@eecs.umich.edu#include "debug/Decoder.hh"
379022Sgblack@eecs.umich.edu
389022Sgblack@eecs.umich.edunamespace X86ISA
399022Sgblack@eecs.umich.edu{
409376Sgblack@eecs.umich.edu
419376Sgblack@eecs.umich.eduDecoder::State
429376Sgblack@eecs.umich.eduDecoder::doResetState()
439023Sgblack@eecs.umich.edu{
449023Sgblack@eecs.umich.edu    origPC = basePC + offset;
459023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Setting origPC to %#x\n", origPC);
469376Sgblack@eecs.umich.edu    instBytes = &decodePages->lookup(origPC);
479376Sgblack@eecs.umich.edu    chunkIdx = 0;
489376Sgblack@eecs.umich.edu
499023Sgblack@eecs.umich.edu    emi.rex = 0;
509023Sgblack@eecs.umich.edu    emi.legacy = 0;
5110924Snilay@cs.wisc.edu    emi.vex = 0;
5210924Snilay@cs.wisc.edu
5310593Sgabeblack@google.com    emi.opcode.type = BadOpcode;
549023Sgblack@eecs.umich.edu    emi.opcode.op = 0;
559023Sgblack@eecs.umich.edu
569023Sgblack@eecs.umich.edu    immediateCollected = 0;
579023Sgblack@eecs.umich.edu    emi.immediate = 0;
589023Sgblack@eecs.umich.edu    emi.displacement = 0;
599023Sgblack@eecs.umich.edu    emi.dispSize = 0;
609023Sgblack@eecs.umich.edu
619023Sgblack@eecs.umich.edu    emi.modRM = 0;
629023Sgblack@eecs.umich.edu    emi.sib = 0;
639376Sgblack@eecs.umich.edu
649376Sgblack@eecs.umich.edu    if (instBytes->si) {
659376Sgblack@eecs.umich.edu        return FromCacheState;
669376Sgblack@eecs.umich.edu    } else {
679376Sgblack@eecs.umich.edu        instBytes->chunks.clear();
689376Sgblack@eecs.umich.edu        return PrefixState;
699376Sgblack@eecs.umich.edu    }
709023Sgblack@eecs.umich.edu}
719023Sgblack@eecs.umich.edu
729376Sgblack@eecs.umich.eduvoid
739376Sgblack@eecs.umich.eduDecoder::process()
749023Sgblack@eecs.umich.edu{
759023Sgblack@eecs.umich.edu    //This function drives the decoder state machine.
769023Sgblack@eecs.umich.edu
779023Sgblack@eecs.umich.edu    //Some sanity checks. You shouldn't try to process more bytes if
789023Sgblack@eecs.umich.edu    //there aren't any, and you shouldn't overwrite an already
799023Sgblack@eecs.umich.edu    //decoder ExtMachInst.
809023Sgblack@eecs.umich.edu    assert(!outOfBytes);
819023Sgblack@eecs.umich.edu    assert(!instDone);
829023Sgblack@eecs.umich.edu
839376Sgblack@eecs.umich.edu    if (state == ResetState)
849376Sgblack@eecs.umich.edu        state = doResetState();
859376Sgblack@eecs.umich.edu    if (state == FromCacheState) {
869376Sgblack@eecs.umich.edu        state = doFromCacheState();
879376Sgblack@eecs.umich.edu    } else {
889376Sgblack@eecs.umich.edu        instBytes->chunks.push_back(fetchChunk);
899376Sgblack@eecs.umich.edu    }
909376Sgblack@eecs.umich.edu
919023Sgblack@eecs.umich.edu    //While there's still something to do...
929376Sgblack@eecs.umich.edu    while (!instDone && !outOfBytes) {
939023Sgblack@eecs.umich.edu        uint8_t nextByte = getNextByte();
949376Sgblack@eecs.umich.edu        switch (state) {
959023Sgblack@eecs.umich.edu          case PrefixState:
969023Sgblack@eecs.umich.edu            state = doPrefixState(nextByte);
979023Sgblack@eecs.umich.edu            break;
9810924Snilay@cs.wisc.edu
9910924Snilay@cs.wisc.edu          case TwoByteVexState:
10010924Snilay@cs.wisc.edu            state = doTwoByteVexState(nextByte);
10110924Snilay@cs.wisc.edu            break;
10210924Snilay@cs.wisc.edu
10310924Snilay@cs.wisc.edu          case ThreeByteVexFirstState:
10410924Snilay@cs.wisc.edu            state = doThreeByteVexFirstState(nextByte);
10510924Snilay@cs.wisc.edu            break;
10610924Snilay@cs.wisc.edu
10710924Snilay@cs.wisc.edu          case ThreeByteVexSecondState:
10810924Snilay@cs.wisc.edu            state = doThreeByteVexSecondState(nextByte);
10910924Snilay@cs.wisc.edu            break;
11010924Snilay@cs.wisc.edu
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
22510924Snilay@cs.wisc.edu      case Vex2Prefix:
22610924Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found VEX two-byte prefix %#x.\n", nextByte);
22710924Snilay@cs.wisc.edu        emi.vex.zero = nextByte;
22810924Snilay@cs.wisc.edu        nextState = TwoByteVexState;
22910924Snilay@cs.wisc.edu        break;
23010924Snilay@cs.wisc.edu
23110924Snilay@cs.wisc.edu      case Vex3Prefix:
23210924Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found VEX three-byte prefix %#x.\n", nextByte);
23310924Snilay@cs.wisc.edu        emi.vex.zero = nextByte;
23410924Snilay@cs.wisc.edu        nextState = ThreeByteVexFirstState;
23510924Snilay@cs.wisc.edu        break;
23610924Snilay@cs.wisc.edu
2379023Sgblack@eecs.umich.edu      case 0:
23810593Sgabeblack@google.com        nextState = OneByteOpcodeState;
2399023Sgblack@eecs.umich.edu        break;
24010924Snilay@cs.wisc.edu
2419023Sgblack@eecs.umich.edu      default:
2429023Sgblack@eecs.umich.edu        panic("Unrecognized prefix %#x\n", nextByte);
2439023Sgblack@eecs.umich.edu    }
2449023Sgblack@eecs.umich.edu    return nextState;
2459023Sgblack@eecs.umich.edu}
2469023Sgblack@eecs.umich.edu
24710924Snilay@cs.wisc.eduDecoder::State
24810924Snilay@cs.wisc.eduDecoder::doTwoByteVexState(uint8_t nextByte)
24910924Snilay@cs.wisc.edu{
25010924Snilay@cs.wisc.edu    assert(emi.vex.zero == 0xc5);
25110924Snilay@cs.wisc.edu    consumeByte();
25210924Snilay@cs.wisc.edu    TwoByteVex tbe = 0;
25310924Snilay@cs.wisc.edu    tbe.first = nextByte;
25410924Snilay@cs.wisc.edu
25510924Snilay@cs.wisc.edu    emi.vex.first.r = tbe.first.r;
25610924Snilay@cs.wisc.edu    emi.vex.first.x = 1;
25710924Snilay@cs.wisc.edu    emi.vex.first.b = 1;
25810924Snilay@cs.wisc.edu    emi.vex.first.map_select = 1;
25910924Snilay@cs.wisc.edu
26010924Snilay@cs.wisc.edu    emi.vex.second.w = 0;
26110924Snilay@cs.wisc.edu    emi.vex.second.vvvv = tbe.first.vvvv;
26210924Snilay@cs.wisc.edu    emi.vex.second.l = tbe.first.l;
26310924Snilay@cs.wisc.edu    emi.vex.second.pp = tbe.first.pp;
26410924Snilay@cs.wisc.edu
26510924Snilay@cs.wisc.edu    emi.opcode.type = Vex;
26610924Snilay@cs.wisc.edu    return OneByteOpcodeState;
26710924Snilay@cs.wisc.edu}
26810924Snilay@cs.wisc.edu
26910924Snilay@cs.wisc.eduDecoder::State
27010924Snilay@cs.wisc.eduDecoder::doThreeByteVexFirstState(uint8_t nextByte)
27110924Snilay@cs.wisc.edu{
27210924Snilay@cs.wisc.edu    consumeByte();
27310924Snilay@cs.wisc.edu    emi.vex.first = nextByte;
27410924Snilay@cs.wisc.edu    return ThreeByteVexSecondState;
27510924Snilay@cs.wisc.edu}
27610924Snilay@cs.wisc.edu
27710924Snilay@cs.wisc.eduDecoder::State
27810924Snilay@cs.wisc.eduDecoder::doThreeByteVexSecondState(uint8_t nextByte)
27910924Snilay@cs.wisc.edu{
28010924Snilay@cs.wisc.edu    consumeByte();
28110924Snilay@cs.wisc.edu    emi.vex.second = nextByte;
28210924Snilay@cs.wisc.edu    emi.opcode.type = Vex;
28310924Snilay@cs.wisc.edu    return OneByteOpcodeState;
28410924Snilay@cs.wisc.edu}
28510924Snilay@cs.wisc.edu
28610593Sgabeblack@google.com// Load the first opcode byte. Determine if there are more opcode bytes, and
28710593Sgabeblack@google.com// if not, what immediate and/or ModRM is needed.
2889376Sgblack@eecs.umich.eduDecoder::State
28910593Sgabeblack@google.comDecoder::doOneByteOpcodeState(uint8_t nextByte)
2909023Sgblack@eecs.umich.edu{
2919023Sgblack@eecs.umich.edu    State nextState = ErrorState;
2929023Sgblack@eecs.umich.edu    consumeByte();
29310924Snilay@cs.wisc.edu
29410924Snilay@cs.wisc.edu    if (emi.vex.zero != 0) {
29510924Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found VEX opcode %#x.\n", nextByte);
29610924Snilay@cs.wisc.edu        emi.opcode.op = nextByte;
29710924Snilay@cs.wisc.edu        const uint8_t opcode_map = emi.vex.first.map_select;
29810924Snilay@cs.wisc.edu        nextState = processExtendedOpcode(ImmediateTypeVex[opcode_map]);
29910924Snilay@cs.wisc.edu    } else if (nextByte == 0x0f) {
30010593Sgabeblack@google.com        nextState = TwoByteOpcodeState;
30110593Sgabeblack@google.com        DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
30210593Sgabeblack@google.com    } else {
30310593Sgabeblack@google.com        DPRINTF(Decoder, "Found one byte opcode %#x.\n", nextByte);
30410593Sgabeblack@google.com        emi.opcode.type = OneByteOpcode;
3059023Sgblack@eecs.umich.edu        emi.opcode.op = nextByte;
3069023Sgblack@eecs.umich.edu
30710593Sgabeblack@google.com        nextState = processOpcode(ImmediateTypeOneByte, UsesModRMOneByte,
30810593Sgabeblack@google.com                                  nextByte >= 0xA0 && nextByte <= 0xA3);
30910593Sgabeblack@google.com    }
31010593Sgabeblack@google.com    return nextState;
31110593Sgabeblack@google.com}
3129023Sgblack@eecs.umich.edu
31310593Sgabeblack@google.com// Load the second opcode byte. Determine if there are more opcode bytes, and
31410593Sgabeblack@google.com// if not, what immediate and/or ModRM is needed.
31510593Sgabeblack@google.comDecoder::State
31610593Sgabeblack@google.comDecoder::doTwoByteOpcodeState(uint8_t nextByte)
31710593Sgabeblack@google.com{
31810593Sgabeblack@google.com    State nextState = ErrorState;
31910593Sgabeblack@google.com    consumeByte();
32010593Sgabeblack@google.com    if (nextByte == 0x38) {
32110593Sgabeblack@google.com        nextState = ThreeByte0F38OpcodeState;
32210593Sgabeblack@google.com        DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
32310593Sgabeblack@google.com    } else if (nextByte == 0x3a) {
32410593Sgabeblack@google.com        nextState = ThreeByte0F3AOpcodeState;
32510593Sgabeblack@google.com        DPRINTF(Decoder, "Found opcode escape byte %#x.\n", nextByte);
32610593Sgabeblack@google.com    } else {
32710593Sgabeblack@google.com        DPRINTF(Decoder, "Found two byte opcode %#x.\n", nextByte);
32810593Sgabeblack@google.com        emi.opcode.type = TwoByteOpcode;
32910593Sgabeblack@google.com        emi.opcode.op = nextByte;
3309023Sgblack@eecs.umich.edu
33110593Sgabeblack@google.com        nextState = processOpcode(ImmediateTypeTwoByte, UsesModRMTwoByte);
33210593Sgabeblack@google.com    }
33310593Sgabeblack@google.com    return nextState;
33410593Sgabeblack@google.com}
3359023Sgblack@eecs.umich.edu
33610593Sgabeblack@google.com// Load the third opcode byte and determine what immediate and/or ModRM is
33710593Sgabeblack@google.com// needed.
33810593Sgabeblack@google.comDecoder::State
33910593Sgabeblack@google.comDecoder::doThreeByte0F38OpcodeState(uint8_t nextByte)
34010593Sgabeblack@google.com{
34110593Sgabeblack@google.com    consumeByte();
3429023Sgblack@eecs.umich.edu
34310593Sgabeblack@google.com    DPRINTF(Decoder, "Found three byte 0F38 opcode %#x.\n", nextByte);
34410593Sgabeblack@google.com    emi.opcode.type = ThreeByte0F38Opcode;
34510593Sgabeblack@google.com    emi.opcode.op = nextByte;
3469023Sgblack@eecs.umich.edu
34710593Sgabeblack@google.com    return processOpcode(ImmediateTypeThreeByte0F38, UsesModRMThreeByte0F38);
34810593Sgabeblack@google.com}
3499023Sgblack@eecs.umich.edu
35010593Sgabeblack@google.com// Load the third opcode byte and determine what immediate and/or ModRM is
35110593Sgabeblack@google.com// needed.
35210593Sgabeblack@google.comDecoder::State
35310593Sgabeblack@google.comDecoder::doThreeByte0F3AOpcodeState(uint8_t nextByte)
35410593Sgabeblack@google.com{
35510593Sgabeblack@google.com    consumeByte();
35610593Sgabeblack@google.com
35710593Sgabeblack@google.com    DPRINTF(Decoder, "Found three byte 0F3A opcode %#x.\n", nextByte);
35810593Sgabeblack@google.com    emi.opcode.type = ThreeByte0F3AOpcode;
35910593Sgabeblack@google.com    emi.opcode.op = nextByte;
36010593Sgabeblack@google.com
36110593Sgabeblack@google.com    return processOpcode(ImmediateTypeThreeByte0F3A, UsesModRMThreeByte0F3A);
36210593Sgabeblack@google.com}
36310593Sgabeblack@google.com
36410593Sgabeblack@google.com// Generic opcode processing which determines the immediate size, and whether
36510593Sgabeblack@google.com// or not there's a modrm byte.
36610593Sgabeblack@google.comDecoder::State
36710593Sgabeblack@google.comDecoder::processOpcode(ByteTable &immTable, ByteTable &modrmTable,
36810593Sgabeblack@google.com                       bool addrSizedImm)
36910593Sgabeblack@google.com{
37010593Sgabeblack@google.com    State nextState = ErrorState;
37110593Sgabeblack@google.com    const uint8_t opcode = emi.opcode.op;
37210593Sgabeblack@google.com
37310593Sgabeblack@google.com    //Figure out the effective operand size. This can be overriden to
37410593Sgabeblack@google.com    //a fixed value at the decoder level.
37510593Sgabeblack@google.com    int logOpSize;
37610593Sgabeblack@google.com    if (emi.rex.w)
37710593Sgabeblack@google.com        logOpSize = 3; // 64 bit operand size
37810593Sgabeblack@google.com    else if (emi.legacy.op)
37910593Sgabeblack@google.com        logOpSize = altOp;
38010593Sgabeblack@google.com    else
38110593Sgabeblack@google.com        logOpSize = defOp;
38210593Sgabeblack@google.com
38310593Sgabeblack@google.com    //Set the actual op size
38410593Sgabeblack@google.com    emi.opSize = 1 << logOpSize;
38510593Sgabeblack@google.com
38610593Sgabeblack@google.com    //Figure out the effective address size. This can be overriden to
38710593Sgabeblack@google.com    //a fixed value at the decoder level.
38810593Sgabeblack@google.com    int logAddrSize;
38910593Sgabeblack@google.com    if(emi.legacy.addr)
39010593Sgabeblack@google.com        logAddrSize = altAddr;
39110593Sgabeblack@google.com    else
39210593Sgabeblack@google.com        logAddrSize = defAddr;
39310593Sgabeblack@google.com
39410593Sgabeblack@google.com    //Set the actual address size
39510593Sgabeblack@google.com    emi.addrSize = 1 << logAddrSize;
39610593Sgabeblack@google.com
39710593Sgabeblack@google.com    //Figure out the effective stack width. This can be overriden to
39810593Sgabeblack@google.com    //a fixed value at the decoder level.
39910593Sgabeblack@google.com    emi.stackSize = 1 << stack;
40010593Sgabeblack@google.com
40110593Sgabeblack@google.com    //Figure out how big of an immediate we'll retreive based
40210593Sgabeblack@google.com    //on the opcode.
40310593Sgabeblack@google.com    int immType = immTable[opcode];
40410593Sgabeblack@google.com    if (addrSizedImm)
40510593Sgabeblack@google.com        immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
40610593Sgabeblack@google.com    else
40710593Sgabeblack@google.com        immediateSize = SizeTypeToSize[logOpSize - 1][immType];
40810593Sgabeblack@google.com
40910593Sgabeblack@google.com    //Determine what to expect next
41010593Sgabeblack@google.com    if (modrmTable[opcode]) {
41110593Sgabeblack@google.com        nextState = ModRMState;
41210593Sgabeblack@google.com    } else {
41310593Sgabeblack@google.com        if(immediateSize) {
41410593Sgabeblack@google.com            nextState = ImmediateState;
4159023Sgblack@eecs.umich.edu        } else {
41610593Sgabeblack@google.com            instDone = true;
41710593Sgabeblack@google.com            nextState = ResetState;
4189023Sgblack@eecs.umich.edu        }
4199023Sgblack@eecs.umich.edu    }
4209023Sgblack@eecs.umich.edu    return nextState;
4219023Sgblack@eecs.umich.edu}
4229023Sgblack@eecs.umich.edu
42310924Snilay@cs.wisc.eduDecoder::State
42410924Snilay@cs.wisc.eduDecoder::processExtendedOpcode(ByteTable &immTable)
42510924Snilay@cs.wisc.edu{
42610924Snilay@cs.wisc.edu    //Figure out the effective operand size. This can be overriden to
42710924Snilay@cs.wisc.edu    //a fixed value at the decoder level.
42810924Snilay@cs.wisc.edu    int logOpSize;
42910924Snilay@cs.wisc.edu    if (emi.vex.second.w)
43010924Snilay@cs.wisc.edu        logOpSize = 3; // 64 bit operand size
43110924Snilay@cs.wisc.edu    else if (emi.vex.second.pp == 1)
43210924Snilay@cs.wisc.edu        logOpSize = altOp;
43310924Snilay@cs.wisc.edu    else
43410924Snilay@cs.wisc.edu        logOpSize = defOp;
43510924Snilay@cs.wisc.edu
43610924Snilay@cs.wisc.edu    //Set the actual op size
43710924Snilay@cs.wisc.edu    emi.opSize = 1 << logOpSize;
43810924Snilay@cs.wisc.edu
43910924Snilay@cs.wisc.edu    //Figure out the effective address size. This can be overriden to
44010924Snilay@cs.wisc.edu    //a fixed value at the decoder level.
44110924Snilay@cs.wisc.edu    int logAddrSize;
44210924Snilay@cs.wisc.edu    if(emi.legacy.addr)
44310924Snilay@cs.wisc.edu        logAddrSize = altAddr;
44410924Snilay@cs.wisc.edu    else
44510924Snilay@cs.wisc.edu        logAddrSize = defAddr;
44610924Snilay@cs.wisc.edu
44710924Snilay@cs.wisc.edu    //Set the actual address size
44810924Snilay@cs.wisc.edu    emi.addrSize = 1 << logAddrSize;
44910924Snilay@cs.wisc.edu
45010924Snilay@cs.wisc.edu    //Figure out the effective stack width. This can be overriden to
45110924Snilay@cs.wisc.edu    //a fixed value at the decoder level.
45210924Snilay@cs.wisc.edu    emi.stackSize = 1 << stack;
45310924Snilay@cs.wisc.edu
45410924Snilay@cs.wisc.edu    //Figure out how big of an immediate we'll retreive based
45510924Snilay@cs.wisc.edu    //on the opcode.
45610924Snilay@cs.wisc.edu    const uint8_t opcode = emi.opcode.op;
45710924Snilay@cs.wisc.edu
45810924Snilay@cs.wisc.edu    if (emi.vex.zero == 0xc5 || emi.vex.zero == 0xc4) {
45910924Snilay@cs.wisc.edu        int immType = immTable[opcode];
46010924Snilay@cs.wisc.edu        // Assume 64-bit mode;
46110924Snilay@cs.wisc.edu        immediateSize = SizeTypeToSize[2][immType];
46210924Snilay@cs.wisc.edu    }
46310924Snilay@cs.wisc.edu
46410924Snilay@cs.wisc.edu    if (opcode == 0x77) {
46510924Snilay@cs.wisc.edu        instDone = true;
46610924Snilay@cs.wisc.edu        return ResetState;
46710924Snilay@cs.wisc.edu    }
46810924Snilay@cs.wisc.edu    return ModRMState;
46910924Snilay@cs.wisc.edu}
47010924Snilay@cs.wisc.edu
4719023Sgblack@eecs.umich.edu//Get the ModRM byte and determine what displacement, if any, there is.
4729023Sgblack@eecs.umich.edu//Also determine whether or not to get the SIB byte, displacement, or
4739023Sgblack@eecs.umich.edu//immediate next.
4749376Sgblack@eecs.umich.eduDecoder::State
4759376Sgblack@eecs.umich.eduDecoder::doModRMState(uint8_t nextByte)
4769023Sgblack@eecs.umich.edu{
4779023Sgblack@eecs.umich.edu    State nextState = ErrorState;
47810924Snilay@cs.wisc.edu    ModRM modRM = nextByte;
4799023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte);
4809376Sgblack@eecs.umich.edu    if (defOp == 1) {
4819023Sgblack@eecs.umich.edu        //figure out 16 bit displacement size
4829023Sgblack@eecs.umich.edu        if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
4839023Sgblack@eecs.umich.edu            displacementSize = 2;
4849023Sgblack@eecs.umich.edu        else if (modRM.mod == 1)
4859023Sgblack@eecs.umich.edu            displacementSize = 1;
4869023Sgblack@eecs.umich.edu        else
4879023Sgblack@eecs.umich.edu            displacementSize = 0;
4889023Sgblack@eecs.umich.edu    } else {
4899023Sgblack@eecs.umich.edu        //figure out 32/64 bit displacement size
4909023Sgblack@eecs.umich.edu        if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
4919023Sgblack@eecs.umich.edu            displacementSize = 4;
4929023Sgblack@eecs.umich.edu        else if (modRM.mod == 1)
4939023Sgblack@eecs.umich.edu            displacementSize = 1;
4949023Sgblack@eecs.umich.edu        else
4959023Sgblack@eecs.umich.edu            displacementSize = 0;
4969023Sgblack@eecs.umich.edu    }
4979023Sgblack@eecs.umich.edu
4989023Sgblack@eecs.umich.edu    // The "test" instruction in group 3 needs an immediate, even though
4999023Sgblack@eecs.umich.edu    // the other instructions with the same actual opcode don't.
50010593Sgabeblack@google.com    if (emi.opcode.type == OneByteOpcode && (modRM.reg & 0x6) == 0) {
5019023Sgblack@eecs.umich.edu       if (emi.opcode.op == 0xF6)
5029023Sgblack@eecs.umich.edu           immediateSize = 1;
5039023Sgblack@eecs.umich.edu       else if (emi.opcode.op == 0xF7)
5049023Sgblack@eecs.umich.edu           immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
5059023Sgblack@eecs.umich.edu    }
5069023Sgblack@eecs.umich.edu
5079023Sgblack@eecs.umich.edu    //If there's an SIB, get that next.
5089023Sgblack@eecs.umich.edu    //There is no SIB in 16 bit mode.
5099023Sgblack@eecs.umich.edu    if (modRM.rm == 4 && modRM.mod != 3) {
5109023Sgblack@eecs.umich.edu            // && in 32/64 bit mode)
5119023Sgblack@eecs.umich.edu        nextState = SIBState;
5129023Sgblack@eecs.umich.edu    } else if(displacementSize) {
5139023Sgblack@eecs.umich.edu        nextState = DisplacementState;
5149023Sgblack@eecs.umich.edu    } else if(immediateSize) {
5159023Sgblack@eecs.umich.edu        nextState = ImmediateState;
5169023Sgblack@eecs.umich.edu    } else {
5179023Sgblack@eecs.umich.edu        instDone = true;
5189023Sgblack@eecs.umich.edu        nextState = ResetState;
5199023Sgblack@eecs.umich.edu    }
5209023Sgblack@eecs.umich.edu    //The ModRM byte is consumed no matter what
5219023Sgblack@eecs.umich.edu    consumeByte();
5229023Sgblack@eecs.umich.edu    emi.modRM = modRM;
5239023Sgblack@eecs.umich.edu    return nextState;
5249023Sgblack@eecs.umich.edu}
5259023Sgblack@eecs.umich.edu
5269023Sgblack@eecs.umich.edu//Get the SIB byte. We don't do anything with it at this point, other
5279023Sgblack@eecs.umich.edu//than storing it in the ExtMachInst. Determine if we need to get a
5289023Sgblack@eecs.umich.edu//displacement or immediate next.
5299376Sgblack@eecs.umich.eduDecoder::State
5309376Sgblack@eecs.umich.eduDecoder::doSIBState(uint8_t nextByte)
5319023Sgblack@eecs.umich.edu{
5329023Sgblack@eecs.umich.edu    State nextState = ErrorState;
5339023Sgblack@eecs.umich.edu    emi.sib = nextByte;
5349023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Found SIB byte %#x.\n", nextByte);
5359023Sgblack@eecs.umich.edu    consumeByte();
5369023Sgblack@eecs.umich.edu    if (emi.modRM.mod == 0 && emi.sib.base == 5)
5379023Sgblack@eecs.umich.edu        displacementSize = 4;
5389023Sgblack@eecs.umich.edu    if (displacementSize) {
5399023Sgblack@eecs.umich.edu        nextState = DisplacementState;
5409023Sgblack@eecs.umich.edu    } else if(immediateSize) {
5419023Sgblack@eecs.umich.edu        nextState = ImmediateState;
5429023Sgblack@eecs.umich.edu    } else {
5439023Sgblack@eecs.umich.edu        instDone = true;
5449023Sgblack@eecs.umich.edu        nextState = ResetState;
5459023Sgblack@eecs.umich.edu    }
5469023Sgblack@eecs.umich.edu    return nextState;
5479023Sgblack@eecs.umich.edu}
5489023Sgblack@eecs.umich.edu
5499023Sgblack@eecs.umich.edu//Gather up the displacement, or at least as much of it
5509023Sgblack@eecs.umich.edu//as we can get.
5519376Sgblack@eecs.umich.eduDecoder::State
5529376Sgblack@eecs.umich.eduDecoder::doDisplacementState()
5539023Sgblack@eecs.umich.edu{
5549023Sgblack@eecs.umich.edu    State nextState = ErrorState;
5559023Sgblack@eecs.umich.edu
5569023Sgblack@eecs.umich.edu    getImmediate(immediateCollected,
5579023Sgblack@eecs.umich.edu            emi.displacement,
5589023Sgblack@eecs.umich.edu            displacementSize);
5599023Sgblack@eecs.umich.edu
5609023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Collecting %d byte displacement, got %d bytes.\n",
5619023Sgblack@eecs.umich.edu            displacementSize, immediateCollected);
5629023Sgblack@eecs.umich.edu
5639023Sgblack@eecs.umich.edu    if(displacementSize == immediateCollected) {
5649023Sgblack@eecs.umich.edu        //Reset this for other immediates.
5659023Sgblack@eecs.umich.edu        immediateCollected = 0;
5669023Sgblack@eecs.umich.edu        //Sign extend the displacement
5679023Sgblack@eecs.umich.edu        switch(displacementSize)
5689023Sgblack@eecs.umich.edu        {
5699023Sgblack@eecs.umich.edu          case 1:
5709023Sgblack@eecs.umich.edu            emi.displacement = sext<8>(emi.displacement);
5719023Sgblack@eecs.umich.edu            break;
5729023Sgblack@eecs.umich.edu          case 2:
5739023Sgblack@eecs.umich.edu            emi.displacement = sext<16>(emi.displacement);
5749023Sgblack@eecs.umich.edu            break;
5759023Sgblack@eecs.umich.edu          case 4:
5769023Sgblack@eecs.umich.edu            emi.displacement = sext<32>(emi.displacement);
5779023Sgblack@eecs.umich.edu            break;
5789023Sgblack@eecs.umich.edu          default:
5799023Sgblack@eecs.umich.edu            panic("Undefined displacement size!\n");
5809023Sgblack@eecs.umich.edu        }
5819023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Collected displacement %#x.\n",
5829023Sgblack@eecs.umich.edu                emi.displacement);
5839023Sgblack@eecs.umich.edu        if(immediateSize) {
5849023Sgblack@eecs.umich.edu            nextState = ImmediateState;
5859023Sgblack@eecs.umich.edu        } else {
5869023Sgblack@eecs.umich.edu            instDone = true;
5879023Sgblack@eecs.umich.edu            nextState = ResetState;
5889023Sgblack@eecs.umich.edu        }
5899023Sgblack@eecs.umich.edu
5909023Sgblack@eecs.umich.edu        emi.dispSize = displacementSize;
5919023Sgblack@eecs.umich.edu    }
5929023Sgblack@eecs.umich.edu    else
5939023Sgblack@eecs.umich.edu        nextState = DisplacementState;
5949023Sgblack@eecs.umich.edu    return nextState;
5959023Sgblack@eecs.umich.edu}
5969023Sgblack@eecs.umich.edu
5979023Sgblack@eecs.umich.edu//Gather up the immediate, or at least as much of it
5989023Sgblack@eecs.umich.edu//as we can get
5999376Sgblack@eecs.umich.eduDecoder::State
6009376Sgblack@eecs.umich.eduDecoder::doImmediateState()
6019023Sgblack@eecs.umich.edu{
6029023Sgblack@eecs.umich.edu    State nextState = ErrorState;
6039023Sgblack@eecs.umich.edu
6049023Sgblack@eecs.umich.edu    getImmediate(immediateCollected,
6059023Sgblack@eecs.umich.edu            emi.immediate,
6069023Sgblack@eecs.umich.edu            immediateSize);
6079023Sgblack@eecs.umich.edu
6089023Sgblack@eecs.umich.edu    DPRINTF(Decoder, "Collecting %d byte immediate, got %d bytes.\n",
6099023Sgblack@eecs.umich.edu            immediateSize, immediateCollected);
6109023Sgblack@eecs.umich.edu
6119023Sgblack@eecs.umich.edu    if(immediateSize == immediateCollected)
6129023Sgblack@eecs.umich.edu    {
6139023Sgblack@eecs.umich.edu        //Reset this for other immediates.
6149023Sgblack@eecs.umich.edu        immediateCollected = 0;
6159023Sgblack@eecs.umich.edu
6169023Sgblack@eecs.umich.edu        //XXX Warning! The following is an observed pattern and might
6179023Sgblack@eecs.umich.edu        //not always be true!
6189023Sgblack@eecs.umich.edu
6199023Sgblack@eecs.umich.edu        //Instructions which use 64 bit operands but 32 bit immediates
6209023Sgblack@eecs.umich.edu        //need to have the immediate sign extended to 64 bits.
6219023Sgblack@eecs.umich.edu        //Instructions which use true 64 bit immediates won't be
6229023Sgblack@eecs.umich.edu        //affected, and instructions that use true 32 bit immediates
6239023Sgblack@eecs.umich.edu        //won't notice.
6249023Sgblack@eecs.umich.edu        switch(immediateSize)
6259023Sgblack@eecs.umich.edu        {
6269023Sgblack@eecs.umich.edu          case 4:
6279023Sgblack@eecs.umich.edu            emi.immediate = sext<32>(emi.immediate);
6289023Sgblack@eecs.umich.edu            break;
6299023Sgblack@eecs.umich.edu          case 1:
6309023Sgblack@eecs.umich.edu            emi.immediate = sext<8>(emi.immediate);
6319023Sgblack@eecs.umich.edu        }
6329023Sgblack@eecs.umich.edu
6339023Sgblack@eecs.umich.edu        DPRINTF(Decoder, "Collected immediate %#x.\n",
6349023Sgblack@eecs.umich.edu                emi.immediate);
6359023Sgblack@eecs.umich.edu        instDone = true;
6369023Sgblack@eecs.umich.edu        nextState = ResetState;
6379023Sgblack@eecs.umich.edu    }
6389023Sgblack@eecs.umich.edu    else
6399023Sgblack@eecs.umich.edu        nextState = ImmediateState;
6409023Sgblack@eecs.umich.edu    return nextState;
6419023Sgblack@eecs.umich.edu}
6429022Sgblack@eecs.umich.edu
6439376Sgblack@eecs.umich.eduDecoder::InstBytes Decoder::dummy;
6449376Sgblack@eecs.umich.eduDecoder::InstCacheMap Decoder::instCacheMap;
6459024Sgblack@eecs.umich.edu
6469024Sgblack@eecs.umich.eduStaticInstPtr
6479024Sgblack@eecs.umich.eduDecoder::decode(ExtMachInst mach_inst, Addr addr)
6489024Sgblack@eecs.umich.edu{
6499376Sgblack@eecs.umich.edu    DecodeCache::InstMap::iterator iter = instMap->find(mach_inst);
6509376Sgblack@eecs.umich.edu    if (iter != instMap->end())
6519376Sgblack@eecs.umich.edu        return iter->second;
6529376Sgblack@eecs.umich.edu
6539376Sgblack@eecs.umich.edu    StaticInstPtr si = decodeInst(mach_inst);
6549376Sgblack@eecs.umich.edu    (*instMap)[mach_inst] = si;
6559376Sgblack@eecs.umich.edu    return si;
6569376Sgblack@eecs.umich.edu}
6579376Sgblack@eecs.umich.edu
6589376Sgblack@eecs.umich.eduStaticInstPtr
6599376Sgblack@eecs.umich.eduDecoder::decode(PCState &nextPC)
6609376Sgblack@eecs.umich.edu{
6619376Sgblack@eecs.umich.edu    if (!instDone)
6629376Sgblack@eecs.umich.edu        return NULL;
6639376Sgblack@eecs.umich.edu    instDone = false;
6649376Sgblack@eecs.umich.edu    updateNPC(nextPC);
6659376Sgblack@eecs.umich.edu
6669376Sgblack@eecs.umich.edu    StaticInstPtr &si = instBytes->si;
6679376Sgblack@eecs.umich.edu    if (si)
6689024Sgblack@eecs.umich.edu        return si;
6699024Sgblack@eecs.umich.edu
6709376Sgblack@eecs.umich.edu    // We didn't match in the AddrMap, but we still populated an entry. Fix
6719376Sgblack@eecs.umich.edu    // up its byte masks.
6729376Sgblack@eecs.umich.edu    const int chunkSize = sizeof(MachInst);
6739376Sgblack@eecs.umich.edu
6749376Sgblack@eecs.umich.edu    instBytes->lastOffset = offset;
6759376Sgblack@eecs.umich.edu
6769376Sgblack@eecs.umich.edu    Addr firstBasePC = basePC - (instBytes->chunks.size() - 1) * chunkSize;
6779376Sgblack@eecs.umich.edu    Addr firstOffset = origPC - firstBasePC;
6789376Sgblack@eecs.umich.edu    Addr totalSize = instBytes->lastOffset - firstOffset +
6799376Sgblack@eecs.umich.edu        (instBytes->chunks.size() - 1) * chunkSize;
6809376Sgblack@eecs.umich.edu    int start = firstOffset;
6819376Sgblack@eecs.umich.edu    instBytes->masks.clear();
6829376Sgblack@eecs.umich.edu
6839376Sgblack@eecs.umich.edu    while (totalSize) {
6849376Sgblack@eecs.umich.edu        int end = start + totalSize;
6859376Sgblack@eecs.umich.edu        end = (chunkSize < end) ? chunkSize : end;
6869376Sgblack@eecs.umich.edu        int size = end - start;
6879376Sgblack@eecs.umich.edu        int idx = instBytes->masks.size();
6889376Sgblack@eecs.umich.edu
6899376Sgblack@eecs.umich.edu        MachInst maskVal = mask(size * 8) << (start * 8);
6909376Sgblack@eecs.umich.edu        assert(maskVal);
6919376Sgblack@eecs.umich.edu
6929376Sgblack@eecs.umich.edu        instBytes->masks.push_back(maskVal);
6939376Sgblack@eecs.umich.edu        instBytes->chunks[idx] &= instBytes->masks[idx];
6949376Sgblack@eecs.umich.edu        totalSize -= size;
6959376Sgblack@eecs.umich.edu        start = 0;
6969024Sgblack@eecs.umich.edu    }
6979024Sgblack@eecs.umich.edu
6989376Sgblack@eecs.umich.edu    si = decode(emi, origPC);
6999024Sgblack@eecs.umich.edu    return si;
7009024Sgblack@eecs.umich.edu}
7019022Sgblack@eecs.umich.edu
7029022Sgblack@eecs.umich.edu}
703