view graal/com.oracle.max.asmdis/src/com/sun/max/asm/gen/risc/arm/RawInstructions.java @ 4138:82af018d61db

Merge fixes.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 17 Dec 2011 22:03:44 +0100
parents e233f5660da4
children
line wrap: on
line source

/*
 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.max.asm.gen.risc.arm;

import static com.sun.max.asm.gen.Expression.Static.*;
import static com.sun.max.asm.gen.InstructionConstraint.Static.*;
import static com.sun.max.asm.gen.risc.arm.ARMFields.*;

import java.lang.reflect.*;
import java.util.*;

import com.sun.max.asm.*;
import com.sun.max.asm.arm.*;
import com.sun.max.asm.gen.*;
import com.sun.max.asm.gen.risc.*;

/**
 * Definitions of ARM instructions.
 */

public final class RawInstructions extends ARMInstructionDescriptionCreator {
    final Immediate32Argument zero = new Immediate32Argument(0);

    RawInstructions(RiscTemplateCreator templateCreator) {
        super(templateCreator);

        generateBranch();
        generateDataProcessing();
        generateMultiply();
        generateMiscellaneousArithmetic();
        generateStatusRegisterAccess();
        generateLoadAndStore();
        generateLoadAndStoreMultiple();
        generateSemaphore();
        generateExceptionGenerating();
        generateCoprocessor();
    }

    private void generateCoprocessor() {
    }

    private void generateExceptionGenerating() {
        setCurrentArchitectureManualSection("4.1.7");
        define("bkpt", bits_31_28(14), bits_27_20(18), bits_7_4(7), immediate2, immed_19_8(and(rightShift(immediate2, 4), 0xfff)), immed_3_0(and(immediate2, 0xf)));
        setCurrentArchitectureManualSection("4.1.50");
        define("swi", cond, bits_27_24(15), immed_24);
    }

    private void generateSemaphore() {
        setCurrentArchitectureManualSection("4.1.51");
        define("swp", cond, Rd, Rm, ", [", Rn, "]", bits_27_20(16), sbz_11_8(0), bits_7_4(9), ne(Rd, 15), ne(Rm, 15), ne(Rn, 15), ne(Rn, Rd), ne(Rn, Rm));
        setCurrentArchitectureManualSection("4.1.52");
        define("swpb", cond, Rd, Rm, ", [", Rn, "]", bits_27_20(20), sbz_11_8(0), bits_7_4(9), ne(Rd, 15), ne(Rm, 15), ne(Rn, 15), ne(Rn, Rd), ne(Rn, Rm));
    }

    private void generateLoadAndStoreMultiple() {
        // TODO Auto-generated method stub

    }

    private void generateLoadAndStore() {
        // TODO Auto-generated method stub
        defineLoadAndStoreForAddressingModesExceptPostIndexed("4.1.20", "ldr", b(0), l(1));
        defineLoadAndStoreForPostIndexedAddressingModes("4.1.20", "ldr", b(0), l(1), w(0));

        defineLoadAndStoreForAddressingModesExceptPostIndexed("4.1.44", "str", b(0), l(0));
        defineLoadAndStoreForPostIndexedAddressingModes("4.1.44", "str", b(0), l(0), w(0));

//        defineLoadAndStoreForAddressingModesExceptPostIndexed("4.1.21", "ldrb", b(1), l(1));
//        defineLoadAndStoreForPostIndexedAddressingModes("4.1.21", "ldrb", b(1), l(1), w(0));

//        defineLoadAndStoreForAddressingModesExceptPostIndexed("4.1.45", "strb", b(1), l(0));
//        defineLoadAndStoreForPostIndexedAddressingModes("4.1.45", "strb", b(1), l(0), w(0));

//        defineLoadAndStoreForPostIndexedAddressingModes("4.1.22", "ldrbt", b(1), l(1), w(1));

    }

    private void generateStatusRegisterAccess() {
     // TODO Auto-generated method stub
        setCurrentArchitectureManualSection("4.1.31");
        define("mrscpsr", cond, bit_27(0), bit_26(0), bit_25(0), bit_24(1), bit_23(0), r(0), bit_21(0), bit_20(0), sbo_19_16(15), Rd, sbz_11_0(0), ", cpsr").setExternalName("mrs");
        define("mrsspsr", cond, bit_27(0), bit_26(0), bit_25(0), bit_24(1), bit_23(0), r(1), bit_21(0), bit_20(0), sbo_19_16(15), Rd, sbz_11_0(0), ", spsr").setExternalName("mrs");
        //setCurrentArchitectureManualSection("4.1.32");
        //define("msr");
    }

    private void generateMiscellaneousArithmetic() {
        setCurrentArchitectureManualSection("4.1.12");
        define("clz", cond, bits_27_20(22), sbo_19_16(15), Rd, sbo_11_8(15), bits_7_4(1), Rm, ne(Rd, 15), ne(Rm, 15));
    }

    private void generateMultiply() {
        setCurrentArchitectureManualSection("4.1.28");
        define("mla", cond, bits_27_21(1), s, Rd2, Rm, Rs, Rn2, bits_7_4(9), ne(Rd2, Rm), ne(Rd2, 15), ne(Rm, 15), ne(Rs, 15), ne(Rn2, 15));
        setCurrentArchitectureManualSection("4.1.33");
        define("mul", cond, bits_27_21(0), s, Rd2, Rm, Rs, sbz_15_12(0), bits_7_4(9), ne(Rd2, Rm), ne(Rd2, 15), ne(Rm, 15), ne(Rs, 15));
        setCurrentArchitectureManualSection("4.1.39");
        define("smlal", cond, bits_27_21(7), s, RdLo, RdHi, Rm, Rs, bits_7_4(9), ne(RdLo, RdHi), ne(RdLo, Rm), ne(RdHi, Rm), ne(RdHi, 15), ne(RdLo, 15), ne(Rm, 15), ne(Rs, 15));
        setCurrentArchitectureManualSection("4.1.40");
        define("smull", cond, bits_27_21(6), s, RdLo, RdHi, Rm, Rs, bits_7_4(9), ne(RdLo, RdHi), ne(RdLo, Rm), ne(RdHi, Rm), ne(RdHi, 15), ne(RdLo, 15), ne(Rm, 15), ne(Rs, 15));
        setCurrentArchitectureManualSection("4.1.55");
        define("umlal", cond, bits_27_21(5), s, RdLo, RdHi, Rm, Rs, bits_7_4(9), ne(RdLo, RdHi), ne(RdLo, Rm), ne(RdHi, Rm), ne(RdHi, 15), ne(RdLo, 15), ne(Rm, 15), ne(Rs, 15));
        setCurrentArchitectureManualSection("4.1.56");
        define("umull", cond, bits_27_21(4), s, RdLo, RdHi, Rm, Rs, bits_7_4(9), ne(RdLo, RdHi), ne(RdLo, Rm), ne(RdHi, Rm), ne(RdHi, 15), ne(RdLo, 15), ne(Rm, 15), ne(Rs, 15));
    }

    private void generateDataProcessing() {
        final Method validImmedMethod = getPredicateMethod(ARMImmediates.class, "isValidImmediate", int.class);
        final InstructionConstraint immedConstraint = new TestOnlyInstructionConstraint(makePredicate(validImmedMethod, immediate));

        defineDataProcessingForAllAddressingModes("4.1.2", "adc", s, Rn, Rd, 5, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.3", "add", s, Rn, Rd, 4, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.4", "and", s, Rn, Rd, 0, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.6", "bic", s, Rn, Rd, 14, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.13", "cmn", s(1), Rn, sbz_15_12(0), 11, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.14", "cmp", s(1), Rn, sbz_15_12(0), 10, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.15", "eor", s, Rn, Rd, 1, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.29", "mov", s, sbz_19_16(0), Rd, 13, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.34", "mvn", s, sbz_19_16(0), Rd, 15, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.35", "orr", s, Rn, Rd, 12, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.36", "rsb", s, Rn, Rd, 3, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.37", "rsc", s, Rn, Rd, 7, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.38", "sbc", s, Rn, Rd, 6, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.49", "sub", s, Rn, Rd, 2, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.53", "teq", s(1), Rn, sbz_15_12(0), 9, immedConstraint);
        defineDataProcessingForAllAddressingModes("4.1.54", "tst", s(1), Rn, sbz_15_12(0), 8, immedConstraint);
    }

    private void generateBranch() {
        // TODO Auto-generated method stub

    }

    /**
     * Generates instruction descriptions for all 11 addressing modes of data processing instructions.
     *
     * @param mnemonic assembly instruction mnemonic
     * @param sFld option field which decides whether status registers are updated or not
     * @param source first source operand
     * @param dest destination operand
     * @param opc numeric opcode of the assembly instruction
     * @param constraints constraints on the instruction parameters
     */
    public void defineDataProcessingForAllAddressingModes(String section, String mnemonic, Object sFld, Object source, Object dest, int opc, InstructionConstraint... constraints) {

        setCurrentArchitectureManualSection(section);

        define(mnemonic, cond, bits_27_26(0), i(1), opcode(opc), sFld, dest, source, ", #", immediate, constraints, shifter_operand(encodeShifterOperand(immediate)));
        define(mnemonic, cond, bits_27_26(0), i(1), opcode(opc), sFld, dest, source, ", #", immed_8, ", ", rotate_amount, even(rotate_amount), rotate_imm(div(rotate_amount, 2)));
        define(mnemonic, cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, bits_11_7(0), bits_6_4(0));

        define(mnemonic + "lsl", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", lsl #", shift_imm, bits_6_4(0)).setExternalName(mnemonic);
        define(mnemonic + "lsr", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", lsr #", shift_imm2, shift_imm(mod(shift_imm2, 32)), bits_6_4(2)).setExternalName(mnemonic);
        define(mnemonic + "asr", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", asr #", shift_imm2, shift_imm(mod(shift_imm2, 32)), bits_6_4(4)).setExternalName(mnemonic);
        define(mnemonic + "ror", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", ror #", shift_imm.withExcludedExternalTestArguments(zero), bits_6_4(6)).setExternalName(mnemonic);

        define(mnemonic + "lsl", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", lsl ", Rs, bits_7_4(1)).setExternalName(mnemonic);
        define(mnemonic + "lsr", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", lsr ", Rs, bits_7_4(3)).setExternalName(mnemonic);
        define(mnemonic + "asr", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", asr ", Rs, bits_7_4(5)).setExternalName(mnemonic);
        define(mnemonic + "ror", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", ror ", Rs, bits_7_4(7)).setExternalName(mnemonic);

        define(mnemonic + "rrx", cond, bits_27_26(0), i(0), opcode(opc), sFld, dest, source, Rm, ", rrx ", bits_11_4(6)).setExternalName(mnemonic);
    }

    /**
     * Generates instruction descriptions for first 6 out of 9 addressing modes for load and store instructions.
     * @param section
     * @param mnemonic
     * @param bFld
     * @param lFld
     */
    public void defineLoadAndStoreForAddressingModesExceptPostIndexed(String section, String mnemonic, Object bFld, Object lFld) {
        setCurrentArchitectureManualSection(section);

        //Addressing mode 1
        define(mnemonic + "add", cond, bits_27_26(1), Rd, ", [", Rn, i(0), p(1), u(1), bFld, w(0), lFld, ", #+", offset_12, "]").setExternalName(mnemonic);
        define(mnemonic + "sub", cond, bits_27_26(1), Rd, ", [", Rn, i(0), p(1), u(0), bFld, w(0), lFld, ", #-", offset_12.withExcludedExternalTestArguments(zero), "]").setExternalName(mnemonic);

        //Addressing mode 2
        define(mnemonic + "add", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(0), lFld, ", +", Rm, "]", bits_11_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "sub", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(0), lFld, ", -", Rm, "]", bits_11_4(0), ne(Rm, 15)).setExternalName(mnemonic);

        //Addressing mode 3
        define(mnemonic + "addlsl", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(0), lFld, ", +", Rm, ", lsl #", shift_imm, "]", shift(0), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "sublsl", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(0), lFld, ", -", Rm, ", lsl #", shift_imm.withExcludedExternalTestArguments(zero), "]", shift(0), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "addlsr", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(0), lFld, ", +", Rm, ", lsr #", shift_imm2, "]", shift_imm(mod(shift_imm2, 32)), shift(1), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "sublsr", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(0), lFld, ", -", Rm, ", lsr #", shift_imm2, "]", shift_imm(mod(shift_imm2, 32)), shift(1), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "addasr", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(0), lFld, ", +", Rm, ", asr #", shift_imm2, "]", shift_imm(mod(shift_imm2, 32)), shift(2), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "subasr", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(0), lFld, ", -", Rm, ", asr #", shift_imm2, "]", shift_imm(mod(shift_imm2, 32)), shift(2), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "addror", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(0), lFld, ", +", Rm, ", ror #", shift_imm.withExcludedExternalTestArguments(zero), "]",
                shift(3), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "subror", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(0), lFld, ", -", Rm, ", ror #", shift_imm.withExcludedExternalTestArguments(zero), "]",
                shift(3), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "addrrx", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(0), lFld, ", +", Rm, ", rrx", "]", shift_imm(0), shift(3), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "subrrx", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(0), lFld, ", -", Rm, ", rrx", "]", shift_imm(0), shift(3), bit_4(0), ne(Rm, 15)).setExternalName(mnemonic);

        //Addressing mode 4
        define(mnemonic + "addw", cond, bits_27_26(1), Rd, ", [", Rn, i(0), p(1), u(1), bFld, w(1), lFld, ", #+", offset_12, "]", "!", ne(Rd, Rn), ne(Rn, 15)).setExternalName(mnemonic);
        define(mnemonic + "subw", cond, bits_27_26(1), Rd, ", [", Rn, i(0), p(1), u(0), bFld, w(1), lFld, ", #-", offset_12.withExcludedExternalTestArguments(zero), "]", "!", ne(Rd, Rn), ne(Rn, 15)).setExternalName(mnemonic);

        //Addressing mode 5
        define(mnemonic + "addw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(1), lFld, ", +", Rm, "]", bits_11_4(0), "!", ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "subw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(1), lFld, ", -", Rm, "]", bits_11_4(0), "!", ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);

        //Addressing mode 6
        define(mnemonic + "addlslw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(1), lFld, ", +", Rm, ", lsl #", shift_imm, "]", "!", shift(0), bit_4(0), ne(Rd, Rn),
                ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "sublslw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(1), lFld, ", -", Rm, ", lsl #", shift_imm.withExcludedExternalTestArguments(zero), "]", "!", shift(0), bit_4(0), ne(Rd, Rn),
                ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "addlsrw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(1), lFld, ", +", Rm, ", lsr #", shift_imm2, "]", "!", shift_imm(mod(shift_imm2, 32)),
                shift(1), bit_4(0), ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "sublsrw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(1), lFld, ", -", Rm, ", lsr #", shift_imm2, "]", "!", shift_imm(mod(shift_imm2, 32)),
                shift(1), bit_4(0), ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "addasrw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(1), lFld, ", +", Rm, ", asr #", shift_imm2, "]", "!", shift_imm(mod(shift_imm2, 32)),
                shift(2), bit_4(0), ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "subasrw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(1), lFld, ", -", Rm, ", asr #", shift_imm2, "]", "!", shift_imm(mod(shift_imm2, 32)),
                shift(2), bit_4(0), ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "addrorw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(1), lFld, ", +", Rm, ", ror #", shift_imm.withExcludedExternalTestArguments(zero), "]", "!",
                shift(3), bit_4(0), ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "subrorw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(1), lFld, ", -", Rm, ", ror #", shift_imm.withExcludedExternalTestArguments(zero), "]", "!",
                shift(3), bit_4(0), ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "addrrxw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(1), bFld, w(1), lFld, ", +", Rm, ", rrx", "]", "!", shift_imm(0), shift(3), bit_4(0),
                ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "subrrxw", cond, bits_27_26(1), Rd, ", [", Rn, i(1), p(1), u(0), bFld, w(1), lFld, ", -", Rm, ", rrx", "]", "!", shift_imm(0), shift(3), bit_4(0),
                ne(Rd, Rn), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);

    }

    /**
     * Generates instruction descriptions for last 3 post indexed addressing modes for load and store instructions.
     * @param section
     * @param mnemonic
     * @param bFld
     * @param lFld
     */
    public void defineLoadAndStoreForPostIndexedAddressingModes(String section, String mnemonic, Object bFld, Object lFld, Object wFld) {
        //Addressing mode 7
        define(mnemonic + "add" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(0), p(0), u(1), bFld, wFld, lFld, ", #+", offset_12, ne(Rn, 15)).setExternalName(mnemonic);
        define(mnemonic + "sub" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(0), p(0), u(0), bFld, wFld, lFld, ", #-", offset_12.withExcludedExternalTestArguments(zero), ne(Rn, 15)).setExternalName(mnemonic);

        //Addressing mode 8
        define(mnemonic + "add" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(1), bFld, wFld, lFld, ", +", Rm, bits_11_4(0), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);
        define(mnemonic + "sub" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(0), bFld, wFld, lFld, ", -", Rm, bits_11_4(0), ne(Rm, Rn), ne(Rn, 15), ne(Rm, 15)).setExternalName(mnemonic);

        //Addressing mode 9
        define(mnemonic + "addlsl" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(1), bFld, wFld, lFld, ", +", Rm, ", lsl #", shift_imm, shift(0), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "sublsl" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(0), bFld, wFld, lFld, ", -", Rm, ", lsl #", shift_imm.withExcludedExternalTestArguments(zero),
                shift(0), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "addlsr" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(1), bFld, wFld, lFld, ", +", Rm, ", lsr #", shift_imm2, shift_imm(mod(shift_imm2, 32)),
                shift(1), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "sublsr" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(0), bFld, wFld, lFld, ", -", Rm, ", lsr #", shift_imm2, shift_imm(mod(shift_imm2, 32)),
                shift(1), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "addasr" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(1), bFld, wFld, lFld, ", +", Rm, ", asr #", shift_imm2, shift_imm(mod(shift_imm2, 32)),
            shift(2), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "subasr" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(0), bFld, wFld, lFld, ", -", Rm, ", asr #", shift_imm2, shift_imm(mod(shift_imm2, 32)),
            shift(2), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "addror" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(1), bFld, wFld, lFld, ", +", Rm, ", ror #", shift_imm.withExcludedExternalTestArguments(zero),
                shift(3), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "subror" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(0), bFld, wFld, lFld, ", -", Rm, ", ror #", shift_imm.withExcludedExternalTestArguments(zero),
                shift(3), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "addrrx" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(1), bFld, wFld, lFld, ", +", Rm, ", rrx", shift_imm(0), shift(3), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);
        define(mnemonic + "subrrx" + "post", cond, bits_27_26(1), Rd, ", [", Rn, "]", i(1), p(0), u(0), bFld, wFld, lFld, ", -", Rm, ", rrx", shift_imm(0), shift(3), bit_4(0), ne(Rm, 15), ne(Rn, 15), ne(Rm, Rn)).setExternalName(mnemonic);

    }

    /**
     * Encodes the given 32 bit immediate value as an 8 bit immediate value and a 4 bit rotate value.
     *
     * @param term
     *            the 32 bit immediate value
     */
    public static Expression encodeShifterOperand(final Object term) {
        return new Expression() {
            public long evaluate(Template template, List<Argument> arguments) {
                return ARMImmediates.calculateShifter((int) Static.evaluateTerm(term, template, arguments));
            }

            public String valueString() {
                return ARMImmediates.class.getSimpleName() + "." + "calculateShifter(" + Static.termValueString(term) + ")";
            }
        };
    }

}