/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.jnasm.assembler.x86; import java.util.List; import java.util.Map; import org.jnode.assembler.Label; import org.jnode.assembler.x86.X86Register; import org.jnode.jnasm.assembler.Address; import org.jnode.jnasm.assembler.Instruction; import org.jnode.jnasm.assembler.InstructionUtils; import org.jnode.jnasm.assembler.Register; /** * @author Levente S\u00e1ntha (lsantha@users.sourceforge.net) */ public class MMX extends AbstractX86Module { public static final int EMMS_ISN = 0; public static final int MOVD_ISN = EMMS_ISN + 1; public static final int MOVQ_ISN = MOVD_ISN + 1; public static final int PACKUSWB_ISN = MOVQ_ISN + 1; public static final int PADDW_ISN = PACKUSWB_ISN + 1; public static final int PAND_ISN = PADDW_ISN + 1; public static final int PCMPGTW_ISN = PAND_ISN + 1; public static final int PMULLW_ISN = PCMPGTW_ISN + 1; public static final int PSHUFW_ISN = PMULLW_ISN + 1; public static final int PSRLW_ISN = PSHUFW_ISN + 1; public static final int PSUBW_ISN = PSRLW_ISN + 1; public static final int PUNPCKLBW_ISN = PSUBW_ISN + 1; public static final int PXOR_ISN = PUNPCKLBW_ISN + 1; protected static final Map<String, Integer> INSTRUCTION_MAP; private static final String[] MNEMONICS; static { Map<String, Integer> map = InstructionUtils.getInstructionMap(MMX.class); String[] mnemonics = InstructionUtils.getMnemonicArray(map); INSTRUCTION_MAP = map; MNEMONICS = mnemonics; } public MMX(Map<String, Label> labels, Map<String, Integer> constants) { super(labels, constants); } String[] getMnemonics() { return MNEMONICS; } public boolean emit(String mnemonic, List<Object> operands, int operandSize, Instruction instruction) { this.operands = operands; this.operandSize = operandSize; Integer key = INSTRUCTION_MAP.get(mnemonic); if (key == null) return false; switch (key) { case EMMS_ISN: emitEMMS(); break; case MOVD_ISN: emitMOVD(); break; case MOVQ_ISN: emitMOVQ(); break; case PACKUSWB_ISN: emitPACKUSWB(); break; case PADDW_ISN: emitPADDW(); break; case PAND_ISN: emitPAND(); break; case PCMPGTW_ISN: emitPCMPGTW(); break; case PMULLW_ISN: emitPMULLW(); break; case PSHUFW_ISN: emitPSHUFW(); break; case PSRLW_ISN: emitPSRLW(); break; case PSUBW_ISN: emitPSUBW(); break; case PUNPCKLBW_ISN: emitPUNPCKLBW(); break; case PXOR_ISN: emitPXOR(); break; default: throw new Error("Invalid instruction binding " + key + " for " + mnemonic); } return true; } private void emitEMMS() { stream.writeEMMS(); } private void emitMOVD() { int addr = getAddressingMode(2); switch (addr) { case RE_ADDR: X86Register.MMX r = getRegMMX(0); Address ind = getAddress(1); stream.writeMOVD(operandSize, r, getRegister(ind.getImg()), ind.disp); break; case ER_ADDR: ind = getAddress(0); r = getRegMMX(1); stream.writeMOVD(operandSize, getRegister(ind.getImg()), ind.disp, r); break; default: reportAddressingError(MOVD_ISN, addr); } } private void emitMOVQ() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writeMOVQ(r1, r2); break; case RE_ADDR: X86Register.MMX r = getRegMMX(0); Address ind = getAddress(1); stream.writeMOVQ(operandSize, r, getRegister(ind.getImg()), ind.disp); break; case RA_ADDR: r = getRegMMX(0); ind = getAddress(1); stream.writeMOVQ(operandSize, r, ind.disp); break; default: reportAddressingError(MOVQ_ISN, addr); } } private void emitPACKUSWB() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePACKUSWB(r1, r2); break; default: reportAddressingError(PACKUSWB_ISN, addr); } } private void emitPADDW() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePADDW(r1, r2); break; default: reportAddressingError(PADDW_ISN, addr); } } private void emitPAND() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePAND(r1, r2); break; default: reportAddressingError(PAND_ISN, addr); } } private void emitPCMPGTW() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePCMPGTW(r1, r2); break; default: reportAddressingError(PCMPGTW_ISN, addr); } } private void emitPMULLW() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePMULLW(r1, r2); break; default: reportAddressingError(PMULLW_ISN, addr); } } private void emitPSHUFW() { int addr = getAddressingMode(3); switch (addr) { case RRC_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePSHUFW(r1, r2, getInt(2)); break; default: reportAddressingError(PSHUFW_ISN, addr); } } private void emitPSRLW() { int addr = getAddressingMode(2); switch (addr) { case RC_ADDR: X86Register.MMX r1 = getRegMMX(0); stream.writePSRLW(r1, getInt(1)); break; default: reportAddressingError(PSRLW_ISN, addr); } } private void emitPSUBW() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePSUBW(r1, r2); break; default: reportAddressingError(PSUBW_ISN, addr); } } private void emitPUNPCKLBW() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePUNPCKLBW(r1, r2); break; default: reportAddressingError(PUNPCKLBW_ISN, addr); } } private void emitPXOR() { int addr = getAddressingMode(2); switch (addr) { case RR_ADDR: X86Register.MMX r1 = getRegMMX(0); X86Register.MMX r2 = getRegMMX(1); stream.writePXOR(r1, r2); break; default: reportAddressingError(PXOR_ISN, addr); } } final X86Register.MMX getRegMMX(int i) { return getRegisterMMX(((Register) args[i]).name); } }