From fd45c04cad4891c6216807639482f2b2d6a7b042 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 18 Aug 2009 00:52:45 -0700 Subject: [PATCH] X86: Decode three byte opcodes. --- src/arch/x86/isa/decoder/decoder.isa | 20 +-- .../x86/isa/decoder/three_byte_opcodes.isa | 151 ++++++++++++++++++ src/arch/x86/isa/decoder/two_byte_opcodes.isa | 8 +- src/arch/x86/predecoder.cc | 7 +- src/arch/x86/types.hh | 6 +- 5 files changed, 164 insertions(+), 28 deletions(-) create mode 100644 src/arch/x86/isa/decoder/three_byte_opcodes.isa diff --git a/src/arch/x86/isa/decoder/decoder.isa b/src/arch/x86/isa/decoder/decoder.isa index dcf6ce089..f757abef9 100644 --- a/src/arch/x86/isa/decoder/decoder.isa +++ b/src/arch/x86/isa/decoder/decoder.isa @@ -70,25 +70,7 @@ decode LEGACY_LOCK default Unknown::unknown() //2 byte opcodes ##include "two_byte_opcodes.isa" //3 byte opcodes - 0x3: decode OPCODE_PREFIXA { - 0xF0: decode OPCODE_PREFIXB { - //We don't handle these properly in the predecoder yet, so - //there's no reason to implement them for now. - 0x38: decode OPCODE_OP { - default: FailUnimpl::sseThreeEight(); - } - 0x3A: decode OPCODE_OP { - default: FailUnimpl::sseThreeA(); - } - 0xF0: decode OPCODE_OP { - default: FailUnimpl::threednow(); - } - default: M5InternalError::error( - {{"Unexpected second opcode byte in three byte opcode!"}}); - } - default: M5InternalError::error( - {{"Unexpected first opcode byte in three byte opcode!"}}); - } + ##include "three_byte_opcodes.isa" } //Lock prefix ##include "locked_opcodes.isa" diff --git a/src/arch/x86/isa/decoder/three_byte_opcodes.isa b/src/arch/x86/isa/decoder/three_byte_opcodes.isa new file mode 100644 index 000000000..7587e3dad --- /dev/null +++ b/src/arch/x86/isa/decoder/three_byte_opcodes.isa @@ -0,0 +1,151 @@ +// Copyright (c) 2008 The Regents of The University of Michigan +// All rights reserved. +// +// 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 + +//////////////////////////////////////////////////////////////////// +// +// Decode the three byte opcodes +// +0x3: decode OPCODE_PREFIXA { + 0x0F: decode OPCODE_PREFIXB { + 0x38: decode LEGACY_OP { + format WarnUnimpl { + 1: decode OPCODE_OP { + 0x00: pshufb_Vdq_Wdq(); + 0x01: phaddw_Vdq_Wdq(); + 0x02: phaddd_Vdq_Wdq(); + 0x03: phaddsw_Vdq_Wdq(); + 0x04: pmaddubsw_Vdq_Wdq(); + 0x05: phsubw_Vdq_Wdq(); + 0x06: phsubd_Vdq_Wdq(); + 0x07: phsubsw_Vdq_Wdq(); + 0x08: psignb_Vdq_Wdq(); + 0x09: psignw_Vdq_Wdq(); + 0x0A: psignd_Vdq_Wdq(); + 0x0B: pmulhrsw_Vdq_Wdq(); + 0x10: pblendvb_Vdq_Wdq(); + 0x14: blendvps_Vdq_Wdq(); + 0x15: blendvpd_Vdq_Wdq(); + 0x17: ptest_Vdq_Wdq(); + 0x1C: pabsb_Vdq_Wdq(); + 0x1D: pabsw_Vdq_Wdq(); + 0x1E: pabsd_Vdq_Wdq(); + 0x20: pmovsxbw_Vdq_Udq_or_Mq(); + 0x21: pmovsxbd_Vdq_Udq_or_Md(); + 0x22: pmovsxbq_Vdq_Udq_or_Mw(); + 0x23: pmovsxwd_Vdq_Udq_or_Mq(); + 0x24: pmovsxwq_Vdq_Udq_or_Md(); + 0x25: pmovsxdq_Vdq_Udq_or_Mq(); + 0x28: pmuldq_Vdq_Wdq(); + 0x29: pcmpeqq_Vdq_Wdq(); + 0x2A: movntdqa_Vdq_Mdq(); + 0x2B: packusdw_Vdq_Wdq(); + 0x30: pmovzxbw_Vdq_Udq_or_Mq(); + 0x31: pmovzxbd_Vdq_Udq_or_Md(); + 0x32: pmovzxbq_Vdq_Udq_or_Mw(); + 0x33: pmovzxwd_Vdq_Udq_or_Mq(); + 0x34: pmovzxwq_Vdq_Udq_or_Md(); + 0x35: pmovzxdq_Vdq_Udq_or_Mq(); + 0x37: pcmpgtq_Vdq_Wdq(); + 0x38: pminsb_Vdq_Wdq(); + 0x39: pminsd_Vdq_Wdq(); + 0x3A: pminuw_Vdq_Wdq(); + 0x3B: pminud_Vdq_Wdq(); + 0x3C: pmaxsb_Vdq_Wdq(); + 0x3D: pmaxsd_Vdq_Wdq(); + 0x3E: pmaxuw_Vdq_Wdq(); + 0x3F: pmaxud_Vdq_Wdq(); + 0x40: pmulld_Vdq_Wdq(); + 0x41: phminposuw_Vdq_Wdq(); + default: Inst::UD2(); + } + default: decode LEGACY_REPNE { + 1: decode OPCODE_OP { + 0xF0: crc32_Gd_Eb(); + 0xF1: crc32_Gd_Ev(); + default: Inst::UD2(); + } + default: decode OPCODE_OP { + 0x00: pshufb_Pq_Qq(); + 0x01: phaddw_Pq_Qq(); + 0x02: phaddd_Pq_Qq(); + 0x03: phaddsw_Pq_Qq(); + 0x04: pmaddubsw_Pq_Qq(); + 0x05: phsubw_Pq_Qq(); + 0x06: phsubd_Pq_Qq(); + 0x07: phsubsw_Pq_Qq(); + 0x08: psignb_Pq_Qq(); + 0x09: psignw_Pq_Qq(); + 0x0A: psignd_Pq_Qq(); + 0x0B: pmulhrsw_Pq_Qq(); + 0x1C: pabsb_Pq_Qq(); + 0x1D: pabsw_Pq_Qq(); + 0x1E: pabsd_Pq_Qq(); + default: Inst::UD2(); + } + } + } + } + 0x3A: decode LEGACY_OP { + format WarnUnimpl { + 1: decode OPCODE_OP { + 0x08: roundps_Vdq_Wdq_Ib(); + 0x09: roundpd_Vdq_Wdq_Ib(); + 0x0A: roundss_Vss_Wss_Ib(); + 0x0B: roundsd_Vsd_Wsd_Ib(); + 0x0C: blendps_Vdq_Wdq_Ib(); + 0x0D: blendpd_Vdq_Wdq_Ib(); + 0x0E: pblendw_Vdq_Wdq_Ib(); + 0x0F: palignr_Vdq_Wdq_Ib(); + 0x14: pextrb_Rd_or_Mb_Vdq_Ib(); + 0x15: decode MODRM_MOD { + 0x3: Inst::PEXTRW(Rd,Vdq,Ib); + default: pextrw_Mw_Vdq_Ib(); + } + 0x16: pextrd_pextrq_Ed_or_Eq_Vdq_Ib(); + 0x17: extractps_Ed_Vdq_Ib(); + 0x20: pinsrb_Vdq_Rd_or_Rq_or_Mb_Ib(); + 0x21: insertps_Vdq_Udq_or_Md_Ib(); + 0x22: pinsrd_pinsrq_Vdq_Ed_or_Eq_Ib(); + 0x40: dpps_Vdq_Wdq_Ib(); + 0x41: dppd_Vdq_Wdq_Ib(); + 0x42: pcmpistrm_Vdq_Wdq_Ib(); + 0x43: pcmpistri_Vdq_Wdq_Ib(); + default: Inst::UD2(); + } + default: decode OPCODE_OP { + 0x0F: palignr_Pq_Qq_Ib(); + default: Inst::UD2(); + } + } + } + default: M5InternalError::error( + {{"Unexpected second opcode byte in three byte opcode!"}}); + } + default: M5InternalError::error( + {{"Unexpected first opcode byte in three byte opcode!"}}); +} diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 213e57264..b181770cc 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -428,8 +428,12 @@ 0x7: getsec(); } 0x07: decode OPCODE_OP_BOTTOM3 { - 0x0: three_byte_opcode(); - 0x2: three_byte_opcode(); + 0x0: M5InternalError::error( + {{"Three byte opcode shouldn't be handled by " + "two_byte_opcodes.isa!"}}); + 0x2: M5InternalError::error( + {{"Three byte opcode shouldn't be handled by " + "two_byte_opcodes.isa!"}}); default: UD2(); } format Inst { diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc index f537f92af..026b733bd 100644 --- a/src/arch/x86/predecoder.cc +++ b/src/arch/x86/predecoder.cc @@ -195,7 +195,7 @@ namespace X86ISA State nextState = ErrorState; emi.opcode.num++; //We can't handle 3+ byte opcodes right now - assert(emi.opcode.num < 3); + assert(emi.opcode.num < 4); consumeByte(); if(emi.opcode.num == 1 && nextByte == 0x0f) { @@ -203,11 +203,8 @@ namespace X86ISA DPRINTF(Predecoder, "Found two byte opcode.\n"); emi.opcode.prefixA = nextByte; } - else if(emi.opcode.num == 2 && - (nextByte == 0x0f || - (nextByte & 0xf8) == 0x38)) + else if(emi.opcode.num == 2 && (nextByte == 0x38 || nextByte == 0x3F)) { - panic("Three byte opcodes aren't yet supported!\n"); nextState = OpcodeState; DPRINTF(Predecoder, "Found three byte opcode.\n"); emi.opcode.prefixB = nextByte; diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh index 956ec3216..6fd36b487 100644 --- a/src/arch/x86/types.hh +++ b/src/arch/x86/types.hh @@ -156,8 +156,10 @@ namespace X86ISA uint8_t num; //The first byte detected in a 2+ byte opcode. Should be 0xF0. uint8_t prefixA; - //The second byte detected in a 3+ byte opcode. Could be 0xF0 for - //3dnow instructions, or 0x38-0x3F for some SSE instructions. + //The second byte detected in a 3+ byte opcode. Could be 0x38-0x3F + //for some SSE instructions. 3dNow! instructions are handled as + //two byte opcodes and then split out further by the immediate + //byte. uint8_t prefixB; //The main opcode byte. The highest addressed byte in the opcode. Opcode op;