decoder.cc revision 9023
16782SN/A/*
28683SN/A * Copyright (c) 2011 Google
310973Sdavid.hashe@amd.com * All rights reserved.
46782SN/A *
56782SN/A * Redistribution and use in source and binary forms, with or without
66782SN/A * modification, are permitted provided that the following conditions are
76782SN/A * met: redistributions of source code must retain the above copyright
86782SN/A * notice, this list of conditions and the following disclaimer;
96782SN/A * redistributions in binary form must reproduce the above copyright
106782SN/A * notice, this list of conditions and the following disclaimer in the
116782SN/A * documentation and/or other materials provided with the distribution;
126782SN/A * neither the name of the copyright holders nor the names of its
136782SN/A * contributors may be used to endorse or promote products derived from
146782SN/A * this software without specific prior written permission.
156782SN/A *
166782SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176782SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186782SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196782SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206782SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216782SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226782SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236782SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246782SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256782SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266782SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276782SN/A *
286782SN/A * Authors: Gabe Black
296782SN/A */
3011793Sbrandon.potter@amd.com
3111793Sbrandon.potter@amd.com#include "arch/x86/decoder.hh"
327056SN/A#include "arch/x86/regs/misc.hh"
3313449Sgabeblack@google.com#include "base/misc.hh"
348232SN/A#include "base/trace.hh"
358937SN/A#include "base/types.hh"
369105SN/A#include "cpu/thread_context.hh"
379104SN/A#include "debug/Decoder.hh"
3814184Sgabeblack@google.com
3911108Sdavid.hashe@amd.comnamespace X86ISA
4011308Santhony.gutierrez@amd.com{
416782SN/Avoid Decoder::doReset()
427055SN/A{
437055SN/A    origPC = basePC + offset;
447039SN/A    DPRINTF(Decoder, "Setting origPC to %#x\n", origPC);
457039SN/A    emi.rex = 0;
466782SN/A    emi.legacy = 0;
477039SN/A    emi.opcode.num = 0;
487039SN/A    emi.opcode.op = 0;
497039SN/A    emi.opcode.prefixA = emi.opcode.prefixB = 0;
506782SN/A
516782SN/A    immediateCollected = 0;
526876SN/A    emi.immediate = 0;
536876SN/A    emi.displacement = 0;
546782SN/A    emi.dispSize = 0;
556876SN/A
566782SN/A    emi.modRM = 0;
576782SN/A    emi.sib = 0;
586876SN/A    m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
599105SN/A    emi.mode.mode = m5Reg.mode;
6010919Sbrandon.potter@amd.com    emi.mode.submode = m5Reg.submode;
6110919Sbrandon.potter@amd.com}
6210919Sbrandon.potter@amd.com
6310919Sbrandon.potter@amd.comvoid Decoder::process()
646782SN/A{
656882SN/A    //This function drives the decoder state machine.
666876SN/A
6710970Sdavid.hashe@amd.com    //Some sanity checks. You shouldn't try to process more bytes if
6810980Sdavid.hashe@amd.com    //there aren't any, and you shouldn't overwrite an already
697564SN/A    //decoder ExtMachInst.
708653SN/A    assert(!outOfBytes);
719105SN/A    assert(!instDone);
7211308Santhony.gutierrez@amd.com
736876SN/A    //While there's still something to do...
746876SN/A    while(!instDone && !outOfBytes)
757039SN/A    {
767039SN/A        uint8_t nextByte = getNextByte();
776876SN/A        switch(state)
7811308Santhony.gutierrez@amd.com        {
7911308Santhony.gutierrez@amd.com          case ResetState:
8011308Santhony.gutierrez@amd.com            doReset();
8111308Santhony.gutierrez@amd.com            state = PrefixState;
826882SN/A          case PrefixState:
837056SN/A            state = doPrefixState(nextByte);
846882SN/A            break;
857039SN/A          case OpcodeState:
8611308Santhony.gutierrez@amd.com            state = doOpcodeState(nextByte);
8711308Santhony.gutierrez@amd.com            break;
886782SN/A          case ModRMState:
896782SN/A            state = doModRMState(nextByte);
906782SN/A            break;
916782SN/A          case SIBState:
9211308Santhony.gutierrez@amd.com            state = doSIBState(nextByte);
937039SN/A            break;
947039SN/A          case DisplacementState:
957039SN/A            state = doDisplacementState();
967039SN/A            break;
977039SN/A          case ImmediateState:
986783SN/A            state = doImmediateState();
996782SN/A            break;
1006782SN/A          case ErrorState:
1016782SN/A            panic("Went to the error state in the decoder.\n");
10211061Snilay@cs.wisc.edu          default:
10311025Snilay@cs.wisc.edu            panic("Unrecognized state! %d\n", state);
1046782SN/A        }
10511025Snilay@cs.wisc.edu    }
10611025Snilay@cs.wisc.edu}
10711025Snilay@cs.wisc.edu
1086782SN/A//Either get a prefix and record it in the ExtMachInst, or send the
1096782SN/A//state machine on to get the opcode(s).
1106782SN/ADecoder::State Decoder::doPrefixState(uint8_t nextByte)
1116782SN/A{
1127039SN/A    uint8_t prefix = Prefixes[nextByte];
11311061Snilay@cs.wisc.edu    State nextState = PrefixState;
1146782SN/A    // REX prefixes are only recognized in 64 bit mode.
11511025Snilay@cs.wisc.edu    if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode)
1167039SN/A        prefix = 0;
11711168Sandreas.hansson@arm.com    if (prefix)
1187039SN/A        consumeByte();
1197039SN/A    switch(prefix)
1207039SN/A    {
1217039SN/A        //Operand size override prefixes
1227039SN/A      case OperandSizeOverride:
1236782SN/A        DPRINTF(Decoder, "Found operand size override prefix.\n");
1246782SN/A        emi.legacy.op = true;
1256782SN/A        break;
1266782SN/A      case AddressSizeOverride:
1277039SN/A        DPRINTF(Decoder, "Found address size override prefix.\n");
12811061Snilay@cs.wisc.edu        emi.legacy.addr = true;
12911025Snilay@cs.wisc.edu        break;
1306782SN/A        //Segment override prefixes
13111025Snilay@cs.wisc.edu      case CSOverride:
1327039SN/A      case DSOverride:
13311168Sandreas.hansson@arm.com      case ESOverride:
1347039SN/A      case FSOverride:
1357039SN/A      case GSOverride:
1367039SN/A      case SSOverride:
1376782SN/A        DPRINTF(Decoder, "Found segment override.\n");
1386782SN/A        emi.legacy.seg = prefix;
13910973Sdavid.hashe@amd.com        break;
14010973Sdavid.hashe@amd.com      case Lock:
14110973Sdavid.hashe@amd.com        DPRINTF(Decoder, "Found lock prefix.\n");
14211025Snilay@cs.wisc.edu        emi.legacy.lock = true;
14310973Sdavid.hashe@amd.com        break;
14410973Sdavid.hashe@amd.com      case Rep:
14511025Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found rep prefix.\n");
14610973Sdavid.hashe@amd.com        emi.legacy.rep = true;
14710973Sdavid.hashe@amd.com        break;
14810973Sdavid.hashe@amd.com      case Repne:
14910973Sdavid.hashe@amd.com        DPRINTF(Decoder, "Found repne prefix.\n");
15010973Sdavid.hashe@amd.com        emi.legacy.repne = true;
15110973Sdavid.hashe@amd.com        break;
15210973Sdavid.hashe@amd.com      case RexPrefix:
15310973Sdavid.hashe@amd.com        DPRINTF(Decoder, "Found Rex prefix %#x.\n", nextByte);
15410973Sdavid.hashe@amd.com        emi.rex = nextByte;
15510973Sdavid.hashe@amd.com        break;
15610973Sdavid.hashe@amd.com      case 0:
15710973Sdavid.hashe@amd.com        nextState = OpcodeState;
15810973Sdavid.hashe@amd.com        break;
15910973Sdavid.hashe@amd.com      default:
16010973Sdavid.hashe@amd.com        panic("Unrecognized prefix %#x\n", nextByte);
16110973Sdavid.hashe@amd.com    }
16211049Snilay@cs.wisc.edu    return nextState;
16311049Snilay@cs.wisc.edu}
16411049Snilay@cs.wisc.edu
16511049Snilay@cs.wisc.edu//Load all the opcodes (currently up to 2) and then figure out
16611049Snilay@cs.wisc.edu//what immediate and/or ModRM is needed.
16711118Snilay@cs.wisc.eduDecoder::State Decoder::doOpcodeState(uint8_t nextByte)
16811061Snilay@cs.wisc.edu{
16911049Snilay@cs.wisc.edu    State nextState = ErrorState;
17011049Snilay@cs.wisc.edu    emi.opcode.num++;
17111049Snilay@cs.wisc.edu    //We can't handle 3+ byte opcodes right now
17211049Snilay@cs.wisc.edu    assert(emi.opcode.num < 4);
17311049Snilay@cs.wisc.edu    consumeByte();
17411049Snilay@cs.wisc.edu    if(emi.opcode.num == 1 && nextByte == 0x0f)
17511049Snilay@cs.wisc.edu    {
17611049Snilay@cs.wisc.edu        nextState = OpcodeState;
17711049Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found two byte opcode.\n");
17811049Snilay@cs.wisc.edu        emi.opcode.prefixA = nextByte;
17911049Snilay@cs.wisc.edu    }
18011049Snilay@cs.wisc.edu    else if(emi.opcode.num == 2 && (nextByte == 0x38 || nextByte == 0x3A))
18111049Snilay@cs.wisc.edu    {
18211049Snilay@cs.wisc.edu        nextState = OpcodeState;
18311049Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found three byte opcode.\n");
18411049Snilay@cs.wisc.edu        emi.opcode.prefixB = nextByte;
18511049Snilay@cs.wisc.edu    }
18611049Snilay@cs.wisc.edu    else
18711049Snilay@cs.wisc.edu    {
18811049Snilay@cs.wisc.edu        DPRINTF(Decoder, "Found opcode %#x.\n", nextByte);
18911049Snilay@cs.wisc.edu        emi.opcode.op = nextByte;
19011049Snilay@cs.wisc.edu
19111049Snilay@cs.wisc.edu        //Figure out the effective operand size. This can be overriden to
19211049Snilay@cs.wisc.edu        //a fixed value at the decoder level.
19311049Snilay@cs.wisc.edu        int logOpSize;
19411118Snilay@cs.wisc.edu        if (emi.rex.w)
19511061Snilay@cs.wisc.edu            logOpSize = 3; // 64 bit operand size
19611049Snilay@cs.wisc.edu        else if (emi.legacy.op)
19711049Snilay@cs.wisc.edu            logOpSize = m5Reg.altOp;
19811049Snilay@cs.wisc.edu        else
19911049Snilay@cs.wisc.edu            logOpSize = m5Reg.defOp;
20011049Snilay@cs.wisc.edu
20111049Snilay@cs.wisc.edu        //Set the actual op size
20211049Snilay@cs.wisc.edu        emi.opSize = 1 << logOpSize;
20311049Snilay@cs.wisc.edu
20411049Snilay@cs.wisc.edu        //Figure out the effective address size. This can be overriden to
20511049Snilay@cs.wisc.edu        //a fixed value at the decoder level.
20611049Snilay@cs.wisc.edu        int logAddrSize;
20711049Snilay@cs.wisc.edu        if(emi.legacy.addr)
20811049Snilay@cs.wisc.edu            logAddrSize = m5Reg.altAddr;
20911049Snilay@cs.wisc.edu        else
21011049Snilay@cs.wisc.edu            logAddrSize = m5Reg.defAddr;
21111049Snilay@cs.wisc.edu
2126782SN/A        //Set the actual address size
2137039SN/A        emi.addrSize = 1 << logAddrSize;
21411025Snilay@cs.wisc.edu
2156782SN/A        //Figure out the effective stack width. This can be overriden to
21611025Snilay@cs.wisc.edu        //a fixed value at the decoder level.
21711061Snilay@cs.wisc.edu        emi.stackSize = 1 << m5Reg.stack;
2187039SN/A
2196782SN/A        //Figure out how big of an immediate we'll retreive based
2207039SN/A        //on the opcode.
2217039SN/A        int immType = ImmediateType[emi.opcode.num - 1][nextByte];
22211118Snilay@cs.wisc.edu        if (emi.opcode.num == 1 && nextByte >= 0xA0 && nextByte <= 0xA3)
2237039SN/A            immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
2247039SN/A        else
22511118Snilay@cs.wisc.edu            immediateSize = SizeTypeToSize[logOpSize - 1][immType];
2267039SN/A
2276782SN/A        //Determine what to expect next
2286782SN/A        if (UsesModRM[emi.opcode.num - 1][nextByte]) {
2296782SN/A            nextState = ModRMState;
2306782SN/A        } else {
2316782SN/A            if(immediateSize) {
2327039SN/A                nextState = ImmediateState;
23311025Snilay@cs.wisc.edu            } else {
2346782SN/A                instDone = true;
23511025Snilay@cs.wisc.edu                nextState = ResetState;
2366782SN/A            }
23711061Snilay@cs.wisc.edu        }
2386782SN/A    }
2397039SN/A    return nextState;
2407039SN/A}
2417039SN/A
2427039SN/A//Get the ModRM byte and determine what displacement, if any, there is.
2437039SN/A//Also determine whether or not to get the SIB byte, displacement, or
2447039SN/A//immediate next.
2457039SN/ADecoder::State Decoder::doModRMState(uint8_t nextByte)
2467039SN/A{
2477039SN/A    State nextState = ErrorState;
2487039SN/A    ModRM modRM;
2497039SN/A    modRM = nextByte;
2506782SN/A    DPRINTF(Decoder, "Found modrm byte %#x.\n", nextByte);
2517039SN/A    if (m5Reg.defOp == 1) {
2526782SN/A        //figure out 16 bit displacement size
2536782SN/A        if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
2547839SN/A            displacementSize = 2;
25511086Snilay@cs.wisc.edu        else if (modRM.mod == 1)
2566782SN/A            displacementSize = 1;
25711025Snilay@cs.wisc.edu        else
2587039SN/A            displacementSize = 0;
2597039SN/A    } else {
26011118Snilay@cs.wisc.edu        //figure out 32/64 bit displacement size
2616782SN/A        if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
2627039SN/A            displacementSize = 4;
26311061Snilay@cs.wisc.edu        else if (modRM.mod == 1)
2647454SN/A            displacementSize = 1;
2657039SN/A        else
2667039SN/A            displacementSize = 0;
26711145Sjthestness@gmail.com    }
26811145Sjthestness@gmail.com
26911145Sjthestness@gmail.com    // The "test" instruction in group 3 needs an immediate, even though
27011145Sjthestness@gmail.com    // the other instructions with the same actual opcode don't.
27111145Sjthestness@gmail.com    if (emi.opcode.num == 1 && (modRM.reg & 0x6) == 0) {
27211145Sjthestness@gmail.com       if (emi.opcode.op == 0xF6)
27311145Sjthestness@gmail.com           immediateSize = 1;
2747039SN/A       else if (emi.opcode.op == 0xF7)
2757039SN/A           immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
2767039SN/A    }
2777039SN/A
2787039SN/A    //If there's an SIB, get that next.
2797839SN/A    //There is no SIB in 16 bit mode.
2807039SN/A    if (modRM.rm == 4 && modRM.mod != 3) {
28111086Snilay@cs.wisc.edu            // && in 32/64 bit mode)
28211086Snilay@cs.wisc.edu        nextState = SIBState;
2836782SN/A    } else if(displacementSize) {
28410974Sdavid.hashe@amd.com        nextState = DisplacementState;
28510974Sdavid.hashe@amd.com    } else if(immediateSize) {
28610974Sdavid.hashe@amd.com        nextState = ImmediateState;
2876782SN/A    } else {
2887839SN/A        instDone = true;
2897039SN/A        nextState = ResetState;
2906782SN/A    }
2917805SN/A    //The ModRM byte is consumed no matter what
2926782SN/A    consumeByte();
2936782SN/A    emi.modRM = modRM;
2947039SN/A    return nextState;
29511025Snilay@cs.wisc.edu}
2966782SN/A
29711025Snilay@cs.wisc.edu//Get the SIB byte. We don't do anything with it at this point, other
2987039SN/A//than storing it in the ExtMachInst. Determine if we need to get a
29911118Snilay@cs.wisc.edu//displacement or immediate next.
30011061Snilay@cs.wisc.eduDecoder::State Decoder::doSIBState(uint8_t nextByte)
3017039SN/A{
3027039SN/A    State nextState = ErrorState;
3037039SN/A    emi.sib = nextByte;
3047039SN/A    DPRINTF(Decoder, "Found SIB byte %#x.\n", nextByte);
3057039SN/A    consumeByte();
3067039SN/A    if (emi.modRM.mod == 0 && emi.sib.base == 5)
3076782SN/A        displacementSize = 4;
3086782SN/A    if (displacementSize) {
3096782SN/A        nextState = DisplacementState;
31011025Snilay@cs.wisc.edu    } else if(immediateSize) {
31111025Snilay@cs.wisc.edu        nextState = ImmediateState;
3126782SN/A    } else {
31311025Snilay@cs.wisc.edu        instDone = true;
3147039SN/A        nextState = ResetState;
3156782SN/A    }
31611061Snilay@cs.wisc.edu    return nextState;
3177039SN/A}
3187039SN/A
3196782SN/A//Gather up the displacement, or at least as much of it
3206782SN/A//as we can get.
3216782SN/ADecoder::State Decoder::doDisplacementState()
3227839SN/A{
32311025Snilay@cs.wisc.edu    State nextState = ErrorState;
3246782SN/A
32511025Snilay@cs.wisc.edu    getImmediate(immediateCollected,
32611061Snilay@cs.wisc.edu            emi.displacement,
3277039SN/A            displacementSize);
32811321Ssteve.reinhardt@amd.com
3297839SN/A    DPRINTF(Decoder, "Collecting %d byte displacement, got %d bytes.\n",
3306782SN/A            displacementSize, immediateCollected);
3316782SN/A
3326782SN/A    if(displacementSize == immediateCollected) {
3337839SN/A        //Reset this for other immediates.
33411025Snilay@cs.wisc.edu        immediateCollected = 0;
3356782SN/A        //Sign extend the displacement
33611025Snilay@cs.wisc.edu        switch(displacementSize)
33711061Snilay@cs.wisc.edu        {
3387039SN/A          case 1:
33911321Ssteve.reinhardt@amd.com            emi.displacement = sext<8>(emi.displacement);
3407839SN/A            break;
3416782SN/A          case 2:
3426782SN/A            emi.displacement = sext<16>(emi.displacement);
3436782SN/A            break;
3447039SN/A          case 4:
34511025Snilay@cs.wisc.edu            emi.displacement = sext<32>(emi.displacement);
3466782SN/A            break;
34711061Snilay@cs.wisc.edu          default:
3488828SN/A            panic("Undefined displacement size!\n");
3496782SN/A        }
35011321Ssteve.reinhardt@amd.com        DPRINTF(Decoder, "Collected displacement %#x.\n",
3519171SN/A                emi.displacement);
3526782SN/A        if(immediateSize) {
3536782SN/A            nextState = ImmediateState;
3547039SN/A        } else {
35511087Snilay@cs.wisc.edu            instDone = true;
35611087Snilay@cs.wisc.edu            nextState = ResetState;
35711087Snilay@cs.wisc.edu        }
35811087Snilay@cs.wisc.edu
35911087Snilay@cs.wisc.edu        emi.dispSize = displacementSize;
36011087Snilay@cs.wisc.edu    }
36111087Snilay@cs.wisc.edu    else
36211087Snilay@cs.wisc.edu        nextState = DisplacementState;
36311308Santhony.gutierrez@amd.com    return nextState;
36411308Santhony.gutierrez@amd.com}
36511308Santhony.gutierrez@amd.com
36611308Santhony.gutierrez@amd.com//Gather up the immediate, or at least as much of it
36711308Santhony.gutierrez@amd.com//as we can get
36811321Ssteve.reinhardt@amd.comDecoder::State Decoder::doImmediateState()
36911308Santhony.gutierrez@amd.com{
37011308Santhony.gutierrez@amd.com    State nextState = ErrorState;
37111308Santhony.gutierrez@amd.com
37211308Santhony.gutierrez@amd.com    getImmediate(immediateCollected,
37311308Santhony.gutierrez@amd.com            emi.immediate,
37411308Santhony.gutierrez@amd.com            immediateSize);
37511308Santhony.gutierrez@amd.com
37611308Santhony.gutierrez@amd.com    DPRINTF(Decoder, "Collecting %d byte immediate, got %d bytes.\n",
37711308Santhony.gutierrez@amd.com            immediateSize, immediateCollected);
37811308Santhony.gutierrez@amd.com
37911308Santhony.gutierrez@amd.com    if(immediateSize == immediateCollected)
38011308Santhony.gutierrez@amd.com    {
38111308Santhony.gutierrez@amd.com        //Reset this for other immediates.
38211308Santhony.gutierrez@amd.com        immediateCollected = 0;
38311308Santhony.gutierrez@amd.com
38411308Santhony.gutierrez@amd.com        //XXX Warning! The following is an observed pattern and might
38511321Ssteve.reinhardt@amd.com        //not always be true!
38611308Santhony.gutierrez@amd.com
38711308Santhony.gutierrez@amd.com        //Instructions which use 64 bit operands but 32 bit immediates
38811308Santhony.gutierrez@amd.com        //need to have the immediate sign extended to 64 bits.
38911308Santhony.gutierrez@amd.com        //Instructions which use true 64 bit immediates won't be
39011308Santhony.gutierrez@amd.com        //affected, and instructions that use true 32 bit immediates
39111308Santhony.gutierrez@amd.com        //won't notice.
39211308Santhony.gutierrez@amd.com        switch(immediateSize)
39311308Santhony.gutierrez@amd.com        {
3948683SN/A          case 4:
3956782SN/A            emi.immediate = sext<32>(emi.immediate);
39611061Snilay@cs.wisc.edu            break;
39711061Snilay@cs.wisc.edu          case 1:
39811061Snilay@cs.wisc.edu            emi.immediate = sext<8>(emi.immediate);
3998683SN/A        }
4007039SN/A
4017039SN/A        DPRINTF(Decoder, "Collected immediate %#x.\n",
4028683SN/A                emi.immediate);
4038683SN/A        instDone = true;
4048683SN/A        nextState = ResetState;
4058683SN/A    }
4068683SN/A    else
4078683SN/A        nextState = ImmediateState;
4088683SN/A    return nextState;
4098683SN/A}
4108683SN/A
4118683SN/ADecodeCache Decoder::defaultCache;
4128683SN/A
4137039SN/A}
4147039SN/A