| /* | |
| * Copyright (c) 2007 The Hewlett-Packard Development Company | |
| * Copyright (c) 2013 Advanced Micro Devices, Inc. | |
| * All rights reserved. | |
| * | |
| * The license below extends only to copyright in the software and shall | |
| * not be construed as granting a license to any other intellectual | |
| * property including but not limited to intellectual property relating | |
| * to a hardware implementation of the functionality of the software | |
| * licensed hereunder. You may use the software subject to the license | |
| * terms below provided that you ensure that this notice is replicated | |
| * unmodified and in its entirety in all distributions of the software, | |
| * modified or unmodified, in source code or in binary form. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * Authors: Gabe Black | |
| */ | |
| #include "arch/x86/insts/static_inst.hh" | |
| #include "arch/x86/regs/segment.hh" | |
| #include "cpu/reg_class.hh" | |
| namespace X86ISA | |
| { | |
| void X86StaticInst::printMnemonic(std::ostream &os, | |
| const char * mnemonic) const | |
| { | |
| ccprintf(os, " %s ", mnemonic); | |
| } | |
| void X86StaticInst::printMnemonic(std::ostream &os, | |
| const char * instMnemonic, const char * mnemonic) const | |
| { | |
| ccprintf(os, " %s : %s ", instMnemonic, mnemonic); | |
| } | |
| void X86StaticInst::printSegment(std::ostream &os, int segment) const | |
| { | |
| switch (segment) | |
| { | |
| case SEGMENT_REG_ES: | |
| ccprintf(os, "ES"); | |
| break; | |
| case SEGMENT_REG_CS: | |
| ccprintf(os, "CS"); | |
| break; | |
| case SEGMENT_REG_SS: | |
| ccprintf(os, "SS"); | |
| break; | |
| case SEGMENT_REG_DS: | |
| ccprintf(os, "DS"); | |
| break; | |
| case SEGMENT_REG_FS: | |
| ccprintf(os, "FS"); | |
| break; | |
| case SEGMENT_REG_GS: | |
| ccprintf(os, "GS"); | |
| break; | |
| case SEGMENT_REG_HS: | |
| ccprintf(os, "HS"); | |
| break; | |
| case SEGMENT_REG_TSL: | |
| ccprintf(os, "TSL"); | |
| break; | |
| case SEGMENT_REG_TSG: | |
| ccprintf(os, "TSG"); | |
| break; | |
| case SEGMENT_REG_LS: | |
| ccprintf(os, "LS"); | |
| break; | |
| case SEGMENT_REG_MS: | |
| ccprintf(os, "MS"); | |
| break; | |
| case SYS_SEGMENT_REG_TR: | |
| ccprintf(os, "TR"); | |
| break; | |
| case SYS_SEGMENT_REG_IDTR: | |
| ccprintf(os, "IDTR"); | |
| break; | |
| default: | |
| panic("Unrecognized segment %d\n", segment); | |
| } | |
| } | |
| void | |
| X86StaticInst::printSrcReg(std::ostream &os, int reg, int size) const | |
| { | |
| if (_numSrcRegs > reg) | |
| printReg(os, _srcRegIdx[reg], size); | |
| } | |
| void | |
| X86StaticInst::printDestReg(std::ostream &os, int reg, int size) const | |
| { | |
| if (_numDestRegs > reg) | |
| printReg(os, _destRegIdx[reg], size); | |
| } | |
| void | |
| X86StaticInst::printReg(std::ostream &os, RegId reg, int size) const | |
| { | |
| assert(size == 1 || size == 2 || size == 4 || size == 8); | |
| static const char * abcdFormats[9] = | |
| {"", "%s", "%sx", "", "e%sx", "", "", "", "r%sx"}; | |
| static const char * piFormats[9] = | |
| {"", "%s", "%s", "", "e%s", "", "", "", "r%s"}; | |
| static const char * longFormats[9] = | |
| {"", "r%sb", "r%sw", "", "r%sd", "", "", "", "r%s"}; | |
| static const char * microFormats[9] = | |
| {"", "t%db", "t%dw", "", "t%dd", "", "", "", "t%d"}; | |
| RegIndex reg_idx = reg.index(); | |
| if (reg.isIntReg()) { | |
| const char * suffix = ""; | |
| bool fold = reg_idx & IntFoldBit; | |
| reg_idx &= ~IntFoldBit; | |
| if (fold) | |
| suffix = "h"; | |
| else if (reg_idx < 8 && size == 1) | |
| suffix = "l"; | |
| switch (reg_idx) { | |
| case INTREG_RAX: | |
| ccprintf(os, abcdFormats[size], "a"); | |
| break; | |
| case INTREG_RBX: | |
| ccprintf(os, abcdFormats[size], "b"); | |
| break; | |
| case INTREG_RCX: | |
| ccprintf(os, abcdFormats[size], "c"); | |
| break; | |
| case INTREG_RDX: | |
| ccprintf(os, abcdFormats[size], "d"); | |
| break; | |
| case INTREG_RSP: | |
| ccprintf(os, piFormats[size], "sp"); | |
| break; | |
| case INTREG_RBP: | |
| ccprintf(os, piFormats[size], "bp"); | |
| break; | |
| case INTREG_RSI: | |
| ccprintf(os, piFormats[size], "si"); | |
| break; | |
| case INTREG_RDI: | |
| ccprintf(os, piFormats[size], "di"); | |
| break; | |
| case INTREG_R8W: | |
| ccprintf(os, longFormats[size], "8"); | |
| break; | |
| case INTREG_R9W: | |
| ccprintf(os, longFormats[size], "9"); | |
| break; | |
| case INTREG_R10W: | |
| ccprintf(os, longFormats[size], "10"); | |
| break; | |
| case INTREG_R11W: | |
| ccprintf(os, longFormats[size], "11"); | |
| break; | |
| case INTREG_R12W: | |
| ccprintf(os, longFormats[size], "12"); | |
| break; | |
| case INTREG_R13W: | |
| ccprintf(os, longFormats[size], "13"); | |
| break; | |
| case INTREG_R14W: | |
| ccprintf(os, longFormats[size], "14"); | |
| break; | |
| case INTREG_R15W: | |
| ccprintf(os, longFormats[size], "15"); | |
| break; | |
| default: | |
| ccprintf(os, microFormats[size], reg_idx - NUM_INTREGS); | |
| } | |
| ccprintf(os, suffix); | |
| } else if (reg.isFloatReg()) { | |
| if (reg_idx < NumMMXRegs) { | |
| ccprintf(os, "%%mmx%d", reg_idx); | |
| return; | |
| } | |
| reg_idx -= NumMMXRegs; | |
| if (reg_idx < NumXMMRegs * 2) { | |
| ccprintf(os, "%%xmm%d_%s", reg_idx / 2, | |
| (reg_idx % 2) ? "high": "low"); | |
| return; | |
| } | |
| reg_idx -= NumXMMRegs * 2; | |
| if (reg_idx < NumMicroFpRegs) { | |
| ccprintf(os, "%%ufp%d", reg_idx); | |
| return; | |
| } | |
| reg_idx -= NumMicroFpRegs; | |
| ccprintf(os, "%%st(%d)", reg_idx); | |
| } else if (reg.isCCReg()) { | |
| ccprintf(os, "%%cc%d", reg_idx); | |
| } else if (reg.isMiscReg()) { | |
| switch (reg_idx) { | |
| default: | |
| ccprintf(os, "%%ctrl%d", reg_idx); | |
| } | |
| } | |
| } | |
| void X86StaticInst::printMem(std::ostream &os, uint8_t segment, | |
| uint8_t scale, RegIndex index, RegIndex base, | |
| uint64_t disp, uint8_t addressSize, bool rip) const | |
| { | |
| bool someAddr = false; | |
| printSegment(os, segment); | |
| os << ":["; | |
| if (rip) { | |
| os << "rip"; | |
| someAddr = true; | |
| } else { | |
| if (scale != 0 && index != ZeroReg) | |
| { | |
| if (scale != 1) | |
| ccprintf(os, "%d*", scale); | |
| printReg(os, InstRegIndex(index), addressSize); | |
| someAddr = true; | |
| } | |
| if (base != ZeroReg) | |
| { | |
| if (someAddr) | |
| os << " + "; | |
| printReg(os, InstRegIndex(base), addressSize); | |
| someAddr = true; | |
| } | |
| } | |
| if (disp != 0) | |
| { | |
| if (someAddr) | |
| os << " + "; | |
| ccprintf(os, "%#x", disp); | |
| someAddr = true; | |
| } | |
| if (!someAddr) | |
| os << "0"; | |
| os << "]"; | |
| } | |
| std::string X86StaticInst::generateDisassembly(Addr pc, | |
| const SymbolTable *symtab) const | |
| { | |
| std::stringstream ss; | |
| printMnemonic(ss, mnemonic); | |
| return ss.str(); | |
| } | |
| } |