/*
* $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.NativeStream;
import org.jnode.assembler.x86.X86Assembler;
import org.jnode.assembler.x86.X86Register;
import org.jnode.jnasm.assembler.Address;
import org.jnode.jnasm.assembler.AssemblerModule;
import org.jnode.jnasm.assembler.Instruction;
import org.jnode.jnasm.assembler.Register;
/**
* @author Levente S\u00e1ntha (lsantha@users.sourceforge.net)
*/
public abstract class AbstractX86Module extends AssemblerModule {
static final int NUL_ARG = 0;
static final int CON_ARG = 1;
static final int REG_ARG = 2;
static final int REL_ARG = 3;
static final int ABS_ARG = 4;
static final int SCL_ARG = 5;
static final int ZSC_ARG = 6;
static final int SEG_ARG = 7;
static final String[] ARG_TYPES = {
"noargument", "constant", "register", "relative", "absolute", "scaled", "simplescaled", "segment"
};
static final int DISP = 3;
static final int DISP_MASK = ((2 << (DISP - 1)) - 1);
static final int N_ADDR = NUL_ARG;
static final int C_ADDR = CON_ARG;
static final int R_ADDR = REG_ARG;
static final int RR_ADDR = REG_ARG | REG_ARG << DISP;
static final int RRR_ADDR = REG_ARG | REG_ARG << DISP | REG_ARG << 2 * DISP;
static final int RRC_ADDR = REG_ARG | REG_ARG << DISP | CON_ARG << 2 * DISP;
static final int RC_ADDR = REG_ARG | CON_ARG << DISP;
static final int RE_ADDR = REG_ARG | REL_ARG << DISP;
static final int REC_ADDR = REG_ARG | REL_ARG << DISP | CON_ARG << 2 * DISP;
static final int RA_ADDR = REG_ARG | ABS_ARG << DISP;
static final int RS_ADDR = REG_ARG | SCL_ARG << DISP;
static final int RZ_ADDR = REG_ARG | ZSC_ARG << DISP;
static final int CR_ADDR = CON_ARG | REG_ARG << DISP;
static final int E_ADDR = REL_ARG;
static final int ER_ADDR = REL_ARG | REG_ARG << DISP;
static final int EC_ADDR = REL_ARG | CON_ARG << DISP;
static final int A_ADDR = ABS_ARG;
static final int AC_ADDR = ABS_ARG | CON_ARG << DISP;
static final int AR_ADDR = ABS_ARG | REG_ARG << DISP;
static final int S_ADDR = SCL_ARG;
static final int SR_ADDR = SCL_ARG | REG_ARG << DISP;
static final int G_ADDR = SEG_ARG;
static final int GR_ADDR = SEG_ARG | REG_ARG << DISP;
static final int GC_ADDR = SEG_ARG | CON_ARG << DISP;
static final int RG_ADDR = REG_ARG | SEG_ARG << DISP;
final Object[] args = new Object[3];
Instruction instruction;
List<Object> operands;
int operandSize;
X86Assembler stream;
AbstractX86Module(Map<String, Label> labels, Map<String, Integer> constants) {
super(labels, constants);
}
public void setNativeStream(NativeStream stream) {
this.stream = (X86Assembler) stream;
}
abstract String[] getMnemonics();
int getAddressingMode(int maxArgs) {
int ret = N_ADDR;
if (maxArgs > 3) {
throw new Error("Invalid number of arguments: " + maxArgs);
}
for (int i = 0; i < maxArgs; i++) {
try {
if (operands == null) break;
Object o = operands.get(i);
if (o == null) break;
if (o instanceof Integer) {
ret |= CON_ARG << DISP * i;
} else if (o instanceof Register) {
ret |= REG_ARG << DISP * i;
} else if (o instanceof Address) {
Address ind = (Address) o;
if (ind.segment) {
ret |= SEG_ARG << DISP * i;
} else if (ind.reg != null && ind.sreg != null) {
ret |= SCL_ARG << DISP * i;
} else if (ind.reg != null) {
ret |= REL_ARG << DISP * i;
} else if (ind.sreg != null) {
ret |= ZSC_ARG << DISP * i;
} else {
ret |= ABS_ARG << DISP * i;
}
} else {
throw new IllegalArgumentException("Unknown operand: " + o + " " + o.getClass().getName());
}
args[i] = o;
} catch (IndexOutOfBoundsException x) {
break;
}
}
return ret;
}
final int getInt(int i) {
return (Integer) args[i];
}
final X86Register.GPR getReg(int i) {
return getRegister(((Register) args[i]).name);
}
final Address getAddress(int i) {
return (Address) args[i];
}
final void reportAddressingError(int instruction, int addressing) {
String err = "";
int ad = addressing;
do {
err += " " + ARG_TYPES[ad & DISP_MASK];
ad >>= DISP;
} while (ad != 0);
throw new IllegalArgumentException(
"Unknown addressing mode " + addressing + " (" + err + " ) for " + getMnemonics()[instruction]);
}
static X86Register.GPR getRegister(String name) {
return X86Register.getGPR(name);
}
static X86Register.MMX getRegisterMMX(String name) {
return (X86Register.MMX) X86Register.getRegister(name);
}
static X86Register.FPU getRegisterFPU(String name) {
return (X86Register.FPU) X86Register.getRegister(name);
}
}