summaryrefslogtreecommitdiff
path: root/src/arch/arm/isa
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/isa')
-rw-r--r--src/arch/arm/isa/base.isa87
-rw-r--r--src/arch/arm/isa/bitfields.isa170
-rw-r--r--src/arch/arm/isa/copyright.txt28
-rw-r--r--src/arch/arm/isa/decoder.isa845
-rw-r--r--src/arch/arm/isa/formats/basic.isa103
-rw-r--r--src/arch/arm/isa/formats/branch.isa307
-rw-r--r--src/arch/arm/isa/formats/formats.isa57
-rw-r--r--src/arch/arm/isa/formats/fp.isa150
-rw-r--r--src/arch/arm/isa/formats/macromem.isa389
-rw-r--r--src/arch/arm/isa/formats/mem.isa593
-rw-r--r--src/arch/arm/isa/formats/pred.isa402
-rw-r--r--src/arch/arm/isa/formats/unimp.isa144
-rw-r--r--src/arch/arm/isa/formats/unknown.isa84
-rw-r--r--src/arch/arm/isa/formats/util.isa217
-rw-r--r--src/arch/arm/isa/includes.isa82
-rw-r--r--src/arch/arm/isa/main.isa63
-rw-r--r--src/arch/arm/isa/operands.isa72
-rw-r--r--src/arch/arm/isa/util.isa282
18 files changed, 4075 insertions, 0 deletions
diff --git a/src/arch/arm/isa/base.isa b/src/arch/arm/isa/base.isa
new file mode 100644
index 000000000..d492bd3cd
--- /dev/null
+++ b/src/arch/arm/isa/base.isa
@@ -0,0 +1,87 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Base class for ARM instructions, and some support functions
+//
+
+//Outputs to decoder.hh
+output header {{
+
+ using namespace ArmISA;
+
+ /**
+ * Base class for all MIPS static instructions.
+ */
+ class ArmStaticInst : public StaticInst
+ {
+ protected:
+
+ // Constructor
+ ArmStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : StaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ /// Print a register name for disassembly given the unique
+ /// dependence tag number (FP or int).
+ void printReg(std::ostream &os, int reg) const;
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+}};
+
+//Ouputs to decoder.cc
+output decoder {{
+
+ void ArmStaticInst::printReg(std::ostream &os, int reg) const
+ {
+ if (reg < FP_Base_DepTag) {
+ ccprintf(os, "r%d", reg);
+ }
+ else {
+ ccprintf(os, "f%d", reg - FP_Base_DepTag);
+ }
+ }
+
+ std::string ArmStaticInst::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ return ss.str();
+ }
+
+}};
+
diff --git a/src/arch/arm/isa/bitfields.isa b/src/arch/arm/isa/bitfields.isa
new file mode 100644
index 000000000..bcb2869b7
--- /dev/null
+++ b/src/arch/arm/isa/bitfields.isa
@@ -0,0 +1,170 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+// Opcode fields
+def bitfield OPCODE <27:25>;
+def bitfield OPCODE_27_25 <27:25>;
+def bitfield OPCODE_24_21 <24:21>;
+def bitfield OPCODE_24_23 <24:23>;
+def bitfield OPCODE_24 <24:24>;
+def bitfield OPCODE_23_20 <23:20>;
+def bitfield OPCODE_23_21 <23:21>;
+def bitfield OPCODE_23 <23:23>;
+def bitfield OPCODE_22_8 <22: 8>;
+def bitfield OPCODE_22_21 <22:21>;
+def bitfield OPCODE_22 <22:22>;
+def bitfield OPCODE_21_20 <21:20>;
+def bitfield OPCODE_20 <20:20>;
+def bitfield OPCODE_19_18 <19:18>;
+def bitfield OPCODE_19 <19:19>;
+def bitfield OPCODE_15_12 <15:12>;
+def bitfield OPCODE_15 <15:15>;
+def bitfield OPCODE_9 < 9: 9>;
+def bitfield OPCODE_7_4 < 7: 4>;
+def bitfield OPCODE_7_5 < 7: 5>;
+def bitfield OPCODE_7_6 < 7: 6>;
+def bitfield OPCODE_7 < 7: 7>;
+def bitfield OPCODE_6_5 < 6: 5>;
+def bitfield OPCODE_6 < 6: 6>;
+def bitfield OPCODE_5 < 5: 5>;
+def bitfield OPCODE_4 < 4: 4>;
+
+// Other
+def bitfield COND_CODE <31:28>;
+def bitfield S_FIELD <20:20>;
+def bitfield RN <19:16>;
+def bitfield RD <15:12>;
+def bitfield SHIFT_SIZE <11: 7>;
+def bitfield SHIFT < 6: 5>;
+def bitfield RM < 3: 0>;
+
+def bitfield RE <20:16>;
+
+def bitfield RS <11: 8>;
+
+def bitfield RDUP <19:16>;
+def bitfield RNDN <15:12>;
+
+def bitfield RDHI <15:12>;
+def bitfield RDLO <11: 8>;
+
+def bitfield U_FIELD <23:23>;
+
+def bitfield PUSWL <24:20>;
+def bitfield PREPOST <24:24>;
+def bitfield UP <23:23>;
+def bitfield PSRUSER <22:22>;
+def bitfield WRITEBACK <21:21>;
+def bitfield LOADOP <20:20>;
+
+def bitfield PUBWL <24:20>;
+def bitfield PUIWL <24:20>;
+def bitfield BYTEACCESS <22:22>;
+
+def bitfield LUAS <23:20>;
+
+def bitfield IMM < 7: 0>;
+def bitfield IMMED_7_4 < 7: 4>;
+def bitfield IMMED_3_0 < 3: 0>;
+
+def bitfield F_MSR <19:19>;
+def bitfield S_MSR <18:18>;
+def bitfield X_MSR <17:17>;
+def bitfield C_MSR <16:16>;
+
+def bitfield Y_6 < 6: 6>;
+def bitfield X_5 < 5: 5>;
+
+def bitfield IMMED_15_4 <15: 4>;
+
+def bitfield W_FIELD <21:21>;
+
+def bitfield ROTATE <11: 8>;
+def bitfield IMMED_7_0 < 7: 0>;
+
+def bitfield T_FIELD <21:21>;
+def bitfield IMMED_11_0 <11: 0>;
+
+def bitfield IMMED_20_16 <20:16>;
+def bitfield IMMED_19_16 <19:16>;
+
+def bitfield IMMED_HI_11_8 <11: 8>;
+def bitfield IMMED_LO_3_0 < 3: 0>;
+
+def bitfield ROT <11:10>;
+
+def bitfield R_FIELD < 5: 5>;
+
+def bitfield CARET <22:22>;
+def bitfield REGLIST <15: 0>;
+
+def bitfield OFFSET <23: 0>;
+def bitfield COPRO <11: 8>;
+def bitfield OP1_7_4 < 7: 4>;
+def bitfield CM < 3: 0>;
+
+def bitfield L_FIELD <22:22>;
+def bitfield CD <15:12>;
+def bitfield OPTION < 7: 0>;
+
+def bitfield OP1_23_20 <23:20>;
+def bitfield CN <19:16>;
+def bitfield OP2_7_5 < 7: 5>;
+
+def bitfield OP1_23_21 <23:21>;
+
+def bitfield IMMED_23_0 <23: 0>;
+def bitfield M_FIELD <17:17>;
+def bitfield A_FIELD < 8: 8>;
+def bitfield I_FIELD < 7: 7>;
+def bitfield F_FIELD < 6: 6>;
+def bitfield MODE < 4: 0>;
+
+def bitfield A_BLX <24:24>;
+
+def bitfield CPNUM <11: 8>;
+// Note that FP Regs are only 3 bits
+def bitfield FN <18:16>;
+def bitfield FD <14:12>;
+def bitfield FPREGIMM < 3: 3>;
+// We can just use 3:0 for FM since the hard-wired FP regs are handled in
+// float_regfile.hh
+def bitfield FM < 3: 0>;
+def bitfield FPIMM < 2: 0>;
+def bitfield PUNWL <24:20>;
+
+// M5 instructions
+def bitfield M5FUNC <7:0>;
+
diff --git a/src/arch/arm/isa/copyright.txt b/src/arch/arm/isa/copyright.txt
new file mode 100644
index 000000000..5a5c487dd
--- /dev/null
+++ b/src/arch/arm/isa/copyright.txt
@@ -0,0 +1,28 @@
+// Copyright (c) 2007, 2008
+// The Florida State University
+// All Rights Reserved
+//
+// This code is part of the M5 simulator.
+//
+// Permission is granted to use, copy, create derivative works and
+// redistribute this software and such derivative works for any
+// purpose, so long as the copyright notice above, this grant of
+// permission, and the disclaimer below appear in all copies made; and
+// so long as the name of The Florida State University is not used in
+// any advertising or publicity pertaining to the use or distribution
+// of this software without specific, written prior authorization.
+//
+// THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
+// FLORIDA STATE UNIVERSITY AS TO ITS FITNESS FOR ANY PURPOSE, AND
+// WITHOUT WARRANTY BY THE FLORIDA STATE UNIVERSITY OF ANY KIND, EITHER
+// EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE. THE REGENTS OF THE FLORIDA STATE UNIVERSITY SHALL NOT BE
+// LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
+// INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
+// ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+// IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGES.
+//
+// Authors: Stephen R. Hines - modified for use in ARM version
+
diff --git a/src/arch/arm/isa/decoder.isa b/src/arch/arm/isa/decoder.isa
new file mode 100644
index 000000000..459c9788e
--- /dev/null
+++ b/src/arch/arm/isa/decoder.isa
@@ -0,0 +1,845 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// The actual ARM ISA decoder
+// --------------------------
+// The following instructions are specified in the ARM ISA
+// Specification. Decoding closely follows the style specified
+// in the ARM ISA specification document starting with Table B.1 or 3-1
+//
+//
+decode COND_CODE default Unknown::unknown() {
+ 0xf: decode COND_CODE {
+ 0x0: decode OPCODE_27_25 {
+ // Just a simple trick to allow us to specify our new uops here
+ 0x0: PredImmOp::addi_uop({{ Raddr = Rn + rotated_imm; }},
+ 'IsMicroop');
+ 0x1: PredImmOp::subi_uop({{ Raddr = Rn - rotated_imm; }},
+ 'IsMicroop');
+ 0x2: ArmLoadMemory::ldr_uop({{ Rd = Mem; }},
+ {{ EA = Raddr + disp; }},
+ inst_flags = [IsMicroop]);
+ 0x3: ArmStoreMemory::str_uop({{ Mem = Rd; }},
+ {{ EA = Raddr + disp; }},
+ inst_flags = [IsMicroop]);
+ 0x4: PredImmOp::addi_rd_uop({{ Rd = Rn + rotated_imm; }},
+ 'IsMicroop');
+ 0x5: PredImmOp::subi_rd_uop({{ Rd = Rn - rotated_imm; }},
+ 'IsMicroop');
+ }
+ 0x1: decode OPCODE_27_25 {
+ 0x0: PredIntOp::mvtd_uop({{ Fd.ud = ((uint64_t) Rhi << 32)|Rlo; }},
+ 'IsMicroop');
+ 0x1: PredIntOp::mvfd_uop({{ Rhi = (Fd.ud >> 32) & 0xffffffff;
+ Rlo = Fd.ud & 0xffffffff; }},
+ 'IsMicroop');
+ 0x2: ArmLoadMemory::ldhi_uop({{ Rhi = Mem; }},
+ {{ EA = Rn + disp; }},
+ inst_flags = [IsMicroop]);
+ 0x3: ArmLoadMemory::ldlo_uop({{ Rlo = Mem; }},
+ {{ EA = Rn + disp; }},
+ inst_flags = [IsMicroop]);
+ 0x4: ArmStoreMemory::sthi_uop({{ Mem = Rhi; }},
+ {{ EA = Rn + disp; }},
+ inst_flags = [IsMicroop]);
+ 0x5: ArmStoreMemory::stlo_uop({{ Mem = Rlo; }},
+ {{ EA = Rn + disp; }},
+ inst_flags = [IsMicroop]);
+ }
+ default: Unknown::unknown(); // TODO: Ignore other NV space for now
+ }
+ format BasicOp{
+ default: decode OPCODE_27_25 {
+ 0x0: decode OPCODE_4 {
+ 0: decode S_FIELD {
+ 0: decode OPCODE_24_21 {
+ format PredIntOp {
+ 0x0: and({{ Rd = Rn & Rm_Imm; }});
+ 0x1: eor({{ Rd = Rn ^ Rm_Imm; }});
+ 0x2: sub({{ Rd = Rn - Rm_Imm; }});
+ 0x3: rsb({{ Rd = Rm_Imm - Rn; }});
+ 0x4: add({{ Rd = Rn + Rm_Imm; }});
+ 0x5: adc({{ Rd = Rn + Rm_Imm + Cpsr<29:>; }});
+ 0x6: sbc({{ Rd = Rn - Rm_Imm + Cpsr<29:> - 1; }});
+ 0x7: rsc({{ Rd = Rm_Imm - Rn + Cpsr<29:> - 1; }});
+ //0x8:mrs_cpsr -- TODO
+ //0x9:msr_cpsr -- TODO
+ //0xa:mrs_spsr -- TODO
+ //0xb:msr_spsr -- TODO
+ 0xc: orr({{ Rd = Rn | Rm_Imm; }});
+ 0xd: mov({{ Rd = Rm_Imm; }});
+ 0xe: bic({{ Rd = Rn & ~Rm_Imm; }});
+ 0xf: mvn({{ Rd = ~Rm_Imm; }});
+ }
+ }
+ 1: decode OPCODE_24_21 {
+ format PredIntOpCc {
+ 0x0: ands({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn & Rm_Imm;
+ }},
+ {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x1: eors({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn ^ Rm_Imm;
+ }},
+ {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x2: subs({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ Rd = resTemp = Rn - val2;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, val2) }},
+ {{ arm_sub_overflow(resTemp, Rn, val2) }});
+ 0x3: rsbs({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ Rd = resTemp = val2 - Rn;
+ }},
+ {{ arm_sub_carry(resTemp, val2, Rn) }},
+ {{ arm_sub_overflow(resTemp, val2, Rn) }});
+ 0x4: adds({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ Rd = resTemp = Rn + val2;
+ }},
+ {{ arm_add_carry(resTemp, Rn, val2) }},
+ {{ arm_add_overflow(resTemp, Rn, val2) }});
+ 0x5: adcs({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ Rd = resTemp = Rn + val2 + Cpsr<29:>;
+ }},
+ {{ arm_add_carry(resTemp, Rn, val2) }},
+ {{ arm_add_overflow(resTemp, Rn, val2) }});
+ 0x6: sbcs({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ Rd = resTemp = Rn - val2 + Cpsr<29:> - 1;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, val2) }},
+ {{ arm_sub_overflow(resTemp, Rn, val2) }});
+ 0x7: rscs({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ Rd = resTemp = val2 - Rn + Cpsr<29:> - 1;
+ }},
+ {{ arm_sub_carry(resTemp, val2, Rn) }},
+ {{ arm_sub_overflow(resTemp, val2, Rn) }});
+ 0x8: tst({{
+ uint32_t resTemp;
+ resTemp = Rn & Rm_Imm;
+ }},
+ {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x9: teq({{
+ uint32_t resTemp;
+ resTemp = Rn ^ Rm_Imm;
+ }},
+ {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xa: cmp({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ resTemp = Rn - val2;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, val2) }},
+ {{ arm_sub_overflow(resTemp, Rn, val2) }});
+ 0xb: cmn({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ resTemp = Rn + val2;
+ }},
+ {{ arm_add_carry(resTemp, Rn, val2) }},
+ {{ arm_add_overflow(resTemp, Rn, val2) }});
+ 0xc: orrs({{
+ uint32_t resTemp,
+ val2 = Rm_Imm;
+ Rd = resTemp = Rn | val2;
+ }},
+ {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xd: movs({{
+ uint32_t resTemp;
+ Rd = resTemp = Rm_Imm;
+ }},
+ {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xe: bics({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn & ~Rm_Imm;
+ }},
+ {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xf: mvns({{
+ uint32_t resTemp;
+ Rd = resTemp = ~Rm_Imm;
+ }},
+ {{ shift_carry_imm(Rm, shift_size, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ }
+ }
+ }
+ 1: decode OPCODE_7 {
+ 0: decode S_FIELD {
+ 0: decode OPCODE_24_21 {
+ format PredIntOp {
+ 0x0: and_rs({{ Rd = Rn & Rm_Rs; }});
+ 0x1: eor_rs({{ Rd = Rn ^ Rm_Rs; }});
+ 0x2: sub_rs({{ Rd = Rn - Rm_Rs; }});
+ 0x3: rsb_rs({{ Rd = Rm_Rs - Rn; }});
+ 0x4: add_rs({{ Rd = Rn + Rm_Rs; }});
+ 0x5: adc_rs({{ Rd = Rn + Rm_Rs + Cpsr<29:>; }});
+ 0x6: sbc_rs({{ Rd = Rn - Rm_Rs + Cpsr<29:> - 1; }});
+ 0x7: rsc_rs({{ Rd = Rm_Rs - Rn + Cpsr<29:> - 1; }});
+ 0xc: orr_rs({{ Rd = Rn | Rm_Rs; }});
+ 0xd: mov_rs({{ Rd = Rm_Rs; }});
+ 0xe: bic_rs({{ Rd = Rn & ~Rm_Rs; }});
+ 0xf: mvn_rs({{ Rd = ~Rm_Rs; }});
+ default: decode OPCODE_7_4 {
+ 0x1: decode OPCODE_24_21 {
+ 0x9: BranchExchange::bx({{ }});
+ 0xb: PredOp::clz({{
+ if (Rm == 0)
+ Rd = 32;
+ else
+ {
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ if (Rm & (1<<(31-i)))
+ break;
+ }
+ Rd = i;
+ }
+ }});
+ }
+ 0x3: decode OPCODE_24_21 {
+ 0x9: BranchExchange::blx({{ LR = NPC; }});
+ }
+ }
+ }
+ }
+ 1: decode OPCODE_24_21 {
+ format PredIntOpCc {
+ 0x0: ands_rs({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn & Rm_Rs;
+ }},
+ {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x1: eors_rs({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn ^ Rm_Rs;
+ }},
+ {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x2: subs_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ Rd = resTemp = Rn - val2;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, val2) }},
+ {{ arm_sub_overflow(resTemp, Rn, val2) }});
+ 0x3: rsbs_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ Rd = resTemp = val2 - Rn;
+ }},
+ {{ arm_sub_carry(resTemp, val2, Rn) }},
+ {{ arm_sub_overflow(resTemp, val2, Rn) }});
+ 0x4: adds_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ Rd = resTemp = Rn + val2;
+ }},
+ {{ arm_add_carry(resTemp, Rn, val2) }},
+ {{ arm_add_overflow(resTemp, Rn, val2) }});
+ 0x5: adcs_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ Rd = resTemp = Rn + val2 + Cpsr<29:>;
+ }},
+ {{ arm_add_carry(resTemp, Rn, val2) }},
+ {{ arm_add_overflow(resTemp, Rn, val2) }});
+ 0x6: sbcs_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ Rd = resTemp = Rn - val2 + Cpsr<29:> - 1;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, val2) }},
+ {{ arm_sub_overflow(resTemp, Rn, val2) }});
+ 0x7: rscs_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ Rd = resTemp = val2 - Rn + Cpsr<29:> - 1;
+ }},
+ {{ arm_sub_carry(resTemp, val2, Rn) }},
+ {{ arm_sub_overflow(resTemp, val2, Rn) }});
+ 0x8: tst_rs({{
+ uint32_t resTemp;
+ resTemp = Rn & Rm_Rs;
+ }},
+ {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x9: teq_rs({{
+ uint32_t resTemp;
+ resTemp = Rn ^ Rm_Rs;
+ }},
+ {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xa: cmp_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ resTemp = Rn - val2;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, val2) }},
+ {{ arm_sub_overflow(resTemp, Rn, val2) }});
+ 0xb: cmn_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ resTemp = Rn + val2;
+ }},
+ {{ arm_add_carry(resTemp, Rn, val2) }},
+ {{ arm_add_overflow(resTemp, Rn, val2) }});
+ 0xc: orrs_rs({{
+ uint32_t resTemp,
+ val2 = Rm_Rs;
+ Rd = resTemp = Rn | val2;
+ }},
+ {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xd: movs_rs({{
+ uint32_t resTemp;
+ Rd = resTemp = Rm_Rs;
+ }},
+ {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xe: bics_rs({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn & ~Rm_Rs;
+ }},
+ {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xf: mvns_rs({{
+ uint32_t resTemp;
+ Rd = resTemp = ~Rm_Rs;
+ }},
+ {{ shift_carry_rs(Rm, Rs, shift, Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ }
+ }
+ }
+ 1: decode OPCODE_6_5 {
+ 0x0: decode OPCODE_24 {
+ 0: decode LUAS {
+ format PredIntOp {
+ 0x0: mul({{ Rn = Rm * Rs; }});
+ 0x1: PredIntOpCc::muls({{
+ uint32_t resTemp;
+ Rn = resTemp = Rm * Rs;
+ }},
+ {{ Cpsr<29:> }},
+ {{ Cpsr<28:> }});
+ 0x2: mla_a({{ Rn = Rm * Rs + Rd; }});
+ 0x8: umull_l({{
+ uint64_t resTemp;
+ resTemp = ((uint64_t)Rm)*((uint64_t)Rs);
+ Rd = (uint32_t)(resTemp & 0xffffffff);
+ Rn = (uint32_t)(resTemp >> 32);
+ }});
+ 0xa: umlal_lu({{
+ uint64_t resTemp;
+ resTemp = ((uint64_t)Rm)*((uint64_t)Rs);
+ resTemp += ((uint64_t)Rn << 32)+((uint64_t)Rd);
+ Rd = (uint32_t)(resTemp & 0xffffffff);
+ Rn = (uint32_t)(resTemp >> 32);
+ }});
+ 0xc: smull_lu({{
+ int64_t resTemp;
+ resTemp = ((int64_t)Rm)*((int64_t)Rs);
+ Rd = (int32_t)(resTemp & 0xffffffff);
+ Rn = (int32_t)(resTemp >> 32);
+ }});
+ }
+ }
+ }
+ 0x1: decode PUIWL {
+ 0x04,0x0c: ArmStoreMemory::strh_i({{ Mem.uh = Rd.uh;
+ Rn = Rn + hilo; }},
+ {{ EA = Rn; }});
+ 0x05,0x0d: ArmLoadMemory::ldrh_il({{ Rd.uh = Mem.uh;
+ Rn = Rn + hilo; }},
+ {{ EA = Rn; }});
+ 0x10,0x18: ArmStoreMemory::strh_p({{ Mem.uh = Rd.uh; }},
+ {{ EA = Rn + Rm; }});
+ 0x11,0x19: ArmLoadMemory::ldrh_pl({{ Rd.uh = Mem.uh; }},
+ {{ EA = Rn + Rm; }});
+ 0x12,0x1a: ArmStoreMemory::strh_pw({{ Mem.uh = Rd.uh;
+ Rn = Rn + Rm; }},
+ {{ EA = Rn + Rm; }});
+ 0x13,0x1b: ArmLoadMemory::ldrh_pwl({{ Rd.uh = Mem.uh;
+ Rn = Rn + Rm; }},
+ {{ EA = Rn + Rm; }});
+ 0x14,0x1c: ArmStoreMemory::strh_pi({{ Mem.uh = Rd.uh; }},
+ {{ EA = Rn + hilo; }});
+ 0x15,0x1d: ArmLoadMemory::ldrh_pil({{ Rd.uh = Mem.uh; }},
+ {{ EA = Rn + hilo; }});
+ 0x16,0x1e: ArmStoreMemory::strh_piw({{ Mem.uh = Rd.uh;
+ Rn = Rn + hilo; }},
+ {{ EA = Rn + hilo; }});
+ 0x17,0x1f: ArmLoadMemory::ldrh_piwl({{ Rd.uh = Mem.uh;
+ Rn = Rn + hilo; }},
+ {{ EA = Rn + hilo; }});
+ }
+ 0x2: decode PUIWL {
+ format ArmLoadMemory {
+ 0x11,0x19: ldrsb_pl({{ Rd.sb = Mem.sb; }},
+ {{ EA = Rn + Rm; }});
+ 0x13,0x1b: ldrsb_pwl({{ Rd.sb = Mem.sb;
+ Rn = Rn + Rm; }},
+ {{ EA = Rn + Rm; }});
+ 0x15,0x1d: ldrsb_pil({{ Rd.sb = Mem.sb; }},
+ {{ EA = Rn + hilo; }});
+ 0x17,0x1f: ldrsb_piwl({{ Rd.sb = Mem.sb;
+ Rn = Rn + hilo; }},
+ {{ EA = Rn + hilo; }});
+ }
+ }
+ 0x3: decode PUIWL {
+ format ArmLoadMemory {
+ 0x11,0x19: ldrsh_pl({{ Rd.sh = Mem.sh; }},
+ {{ EA = Rn + Rm; }});
+ 0x13,0x1b: ldrsh_pwl({{ Rd.sh = Mem.sh;
+ Rn = Rn + Rm; }},
+ {{ EA = Rn + Rm; }});
+ 0x15,0x1d: ldrsh_pil({{ Rd.sh = Mem.sh; }},
+ {{ EA = Rn + hilo; }});
+ 0x17,0x1f: ldrsh_piwl({{ Rd.sh = Mem.sh;
+ Rn = Rn + hilo; }},
+ {{ EA = Rn + hilo; }});
+ }
+ }
+ }
+ }
+ }
+ 0x1: decode S_FIELD {
+ 0: decode OPCODE_24_21 {
+ format PredImmOp {
+ 0x0: andi({{ Rd = Rn & rotated_imm; }});
+ 0x1: eori({{ Rd = Rn ^ rotated_imm; }});
+ 0x2: subi({{ Rd = Rn - rotated_imm; }});
+ 0x3: rsbi({{ Rd = rotated_imm - Rn; }});
+ 0x4: addi({{ Rd = Rn + rotated_imm; }});
+ 0x5: adci({{ Rd = Rn + rotated_imm + Cpsr<29:>; }});
+ 0x6: sbci({{ Rd = Rn - rotated_imm + Cpsr<29:> - 1; }});
+ 0x7: rsci({{ Rd = rotated_imm - Rn + Cpsr<29:> - 1; }});
+ 0xc: orri({{ Rd = Rn | rotated_imm; }});
+ 0xd: decode RN {
+ 0: movi({{ Rd = rotated_imm; }});
+ }
+ 0xe: bici({{ Rd = Rn & ~rotated_imm; }});
+ 0xf: decode RN {
+ 0: mvni({{ Rd = ~rotated_imm; }});
+ }
+ }
+ }
+ 1: decode OPCODE_24_21 {
+ format PredImmOpCc {
+ 0x0: andsi({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn & rotated_imm;
+ }},
+ {{ (rotate ? rotated_carry:Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x1: eorsi({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn ^ rotated_imm;
+ }},
+ {{ (rotate ? rotated_carry:Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x2: subsi({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn - rotated_imm;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, rotated_imm) }},
+ {{ arm_sub_overflow(resTemp, Rn, rotated_imm) }});
+ 0x3: rsbsi({{
+ uint32_t resTemp;
+ Rd = resTemp = rotated_imm - Rn;
+ }},
+ {{ arm_sub_carry(resTemp, rotated_imm, Rn) }},
+ {{ arm_sub_overflow(resTemp, rotated_imm, Rn) }});
+ 0x4: addsi({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn + rotated_imm;
+ }},
+ {{ arm_add_carry(resTemp, Rn, rotated_imm) }},
+ {{ arm_add_overflow(resTemp, Rn, rotated_imm) }});
+ 0x5: adcsi({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn + rotated_imm + Cpsr<29:>;
+ }},
+ {{ arm_add_carry(resTemp, Rn, rotated_imm) }},
+ {{ arm_add_overflow(resTemp, Rn, rotated_imm) }});
+ 0x6: sbcsi({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn -rotated_imm + Cpsr<29:> - 1;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, rotated_imm) }},
+ {{ arm_sub_overflow(resTemp, Rn, rotated_imm) }});
+ 0x7: rscsi({{
+ uint32_t resTemp;
+ Rd = resTemp = rotated_imm - Rn + Cpsr<29:> - 1;
+ }},
+ {{ arm_sub_carry(resTemp, rotated_imm, Rn) }},
+ {{ arm_sub_overflow(resTemp, rotated_imm, Rn) }});
+ 0x8: tsti({{
+ uint32_t resTemp;
+ resTemp = Rn & rotated_imm;
+ }},
+ {{ (rotate ? rotated_carry:Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0x9: teqi({{
+ uint32_t resTemp;
+ resTemp = Rn ^ rotated_imm;
+ }},
+ {{ (rotate ? rotated_carry:Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xa: cmpi({{
+ uint32_t resTemp;
+ resTemp = Rn - rotated_imm;
+ }},
+ {{ arm_sub_carry(resTemp, Rn, rotated_imm) }},
+ {{ arm_sub_overflow(resTemp, Rn, rotated_imm) }});
+ 0xb: cmni({{
+ uint32_t resTemp;
+ resTemp = Rn + rotated_imm;
+ }},
+ {{ arm_add_carry(resTemp, Rn, rotated_imm) }},
+ {{ arm_add_overflow(resTemp, Rn, rotated_imm) }});
+ 0xc: orrsi({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn | rotated_imm;
+ }},
+ {{ (rotate ? rotated_carry:Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xd: movsi({{
+ uint32_t resTemp;
+ Rd = resTemp = rotated_imm;
+ }},
+ {{ (rotate ? rotated_carry:Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xe: bicsi({{
+ uint32_t resTemp;
+ Rd = resTemp = Rn & ~rotated_imm;
+ }},
+ {{ (rotate ? rotated_carry:Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ 0xf: mvnsi({{
+ uint32_t resTemp;
+ Rd = resTemp = ~rotated_imm;
+ }},
+ {{ (rotate ? rotated_carry:Cpsr<29:>) }},
+ {{ Cpsr<28:> }});
+ }
+ }
+ }
+ 0x2: decode PUBWL {
+ // CAREFUL:
+ // Can always do EA + disp, since we negate disp using the UP flag
+ // Post-indexed variants
+ 0x00,0x08: ArmStoreMemory::str_({{ Mem = Rd;
+ Rn = Rn + disp; }},
+ {{ EA = Rn; }});
+ 0x01,0x09: ArmLoadMemory::ldr_l({{ Rd = Mem;
+ Rn = Rn + disp; }},
+ {{ EA = Rn; }});
+ 0x04,0x0c: ArmStoreMemory::strb_b({{ Mem.ub = Rd.ub;
+ Rn = Rn + disp; }},
+ {{ EA = Rn; }});
+ 0x05,0x0d: ArmLoadMemory::ldrb_bl({{ Rd.ub = Mem.ub;
+ Rn = Rn + disp; }},
+ {{ EA = Rn; }});
+ // Pre-indexed variants
+ 0x10,0x18: ArmStoreMemory::str_p({{ Mem = Rd; }});
+ 0x11,0x19: ArmLoadMemory::ldr_pl({{ Rd = Mem; }});
+ 0x12,0x1a: ArmStoreMemory::str_pw({{ Mem = Rd;
+ Rn = Rn + disp; }});
+ 0x13,0x1b: ArmLoadMemory::ldr_pwl({{ Rd = Mem;
+ Rn = Rn + disp; }});
+ 0x14,0x1c: ArmStoreMemory::strb_pb({{ Mem.ub = Rd.ub; }});
+ 0x15,0x1d: ArmLoadMemory::ldrb_pbl({{ Rd.ub = Mem.ub; }});
+ 0x16,0x1e: ArmStoreMemory::strb_pbw({{ Mem.ub = Rd.ub;
+ Rn = Rn + disp; }});
+ 0x17,0x1f: ArmLoadMemory::ldrb_pbwl({{ Rd.ub = Mem.ub;
+ Rn = Rn + disp; }});
+ }
+ 0x3: decode OPCODE_4 {
+ 0: decode PUBWL {
+ 0x00,0x08: ArmStoreMemory::strr_({{
+ Mem = Rd;
+ Rn = Rn + Rm_Imm; }},
+ {{ EA = Rn; }});
+ 0x01,0x09: ArmLoadMemory::ldrr_l({{
+ Rd = Mem;
+ Rn = Rn + Rm_Imm; }},
+ {{ EA = Rn; }});
+ 0x04,0x0c: ArmStoreMemory::strr_b({{
+ Mem.ub = Rd.ub;
+ Rn = Rn + Rm_Imm; }},
+ {{ EA = Rn; }});
+ 0x05,0x0d: ArmLoadMemory::ldrr_bl({{
+ Rd.ub = Mem.ub;
+ Rn = Rn + Rm_Imm; }},
+ {{ EA = Rn; }});
+ 0x10,0x18: ArmStoreMemory::strr_p({{
+ Mem = Rd; }},
+ {{ EA = Rn + Rm_Imm; }});
+ 0x11,0x19: ArmLoadMemory::ldrr_pl({{
+ Rd = Mem; }},
+ {{ EA = Rn + Rm_Imm; }});
+ 0x12,0x1a: ArmStoreMemory::strr_pw({{
+ Mem = Rd;
+ Rn = Rn + Rm_Imm; }},
+ {{ EA = Rn + Rm_Imm; }});
+ 0x13,0x1b: ArmLoadMemory::ldrr_pwl({{
+ Rd = Mem;
+ Rn = Rn + Rm_Imm; }},
+ {{ EA = Rn + Rm_Imm; }});
+ 0x14,0x1c: ArmStoreMemory::strr_pb({{
+ Mem.ub = Rd.ub; }},
+ {{ EA = Rn + Rm_Imm; }});
+ 0x15,0x1d: ArmLoadMemory::ldrr_pbl({{
+ Rd.ub = Mem.ub; }},
+ {{ EA = Rn + Rm_Imm; }});
+ 0x16,0x1e: ArmStoreMemory::strr_pbw({{
+ Mem.ub = Rd.ub;
+ Rn = Rn + Rm_Imm; }},
+ {{ EA = Rn + Rm_Imm; }});
+ 0x17,0x1f: ArmLoadMemory::ldrr_pbwl({{
+ Rd.ub = Mem.ub;
+ Rn = Rn + Rm_Imm; }},
+ {{ EA = Rn + Rm_Imm; }});
+ }
+ }
+ 0x4: decode PUSWL {
+ // Right now we only handle cases when S (PSRUSER) is not set
+ default: ArmMacroStore::ldmstm({{ }});
+ }
+ 0x5: decode OPCODE_24 {
+ // Branch (and Link) Instructions
+ 0: Branch::b({{ }});
+ 1: Branch::bl({{ LR = NPC; }});
+ }
+ 0x6: decode CPNUM {
+ 0x1: decode PUNWL {
+ 0x02,0x0a: decode OPCODE_15 {
+ 0: ArmStoreMemory::stfs_({{ Mem.sf = Fd.sf;
+ Rn = Rn + disp8; }},
+ {{ EA = Rn; }});
+ 1: ArmMacroFPAOp::stfd_({{ }});
+ }
+ 0x03,0x0b: decode OPCODE_15 {
+ 0: ArmLoadMemory::ldfs_({{ Fd.sf = Mem.sf;
+ Rn = Rn + disp8; }},
+ {{ EA = Rn; }});
+ 1: ArmMacroFPAOp::ldfd_({{ }});
+ }
+ 0x06,0x0e: decode OPCODE_15 {
+ 0: ArmMacroFPAOp::stfe_nw({{ }});
+ }
+ 0x07,0x0f: decode OPCODE_15 {
+ 0: ArmMacroFPAOp::ldfe_nw({{ }});
+ }
+ 0x10,0x18: decode OPCODE_15 {
+ 0: ArmStoreMemory::stfs_p({{ Mem.sf = Fd.sf; }},
+ {{ EA = Rn + disp8; }});
+ 1: ArmMacroFPAOp::stfd_p({{ }});
+ }
+ 0x11,0x19: decode OPCODE_15 {
+ 0: ArmLoadMemory::ldfs_p({{ Fd.sf = Mem.sf; }},
+ {{ EA = Rn + disp8; }});
+ 1: ArmMacroFPAOp::ldfd_p({{ }});
+ }
+ 0x12,0x1a: decode OPCODE_15 {
+ 0: ArmStoreMemory::stfs_pw({{ Mem.sf = Fd.sf;
+ Rn = Rn + disp8; }},
+ {{ EA = Rn + disp8; }});
+ 1: ArmMacroFPAOp::stfd_pw({{ }});
+ }
+ 0x13,0x1b: decode OPCODE_15 {
+ 0: ArmLoadMemory::ldfs_pw({{ Fd.sf = Mem.sf;
+ Rn = Rn + disp8; }},
+ {{ EA = Rn + disp8; }});
+ 1: ArmMacroFPAOp::ldfd_pw({{ }});
+ }
+ 0x14,0x1c: decode OPCODE_15 {
+ 0: ArmMacroFPAOp::stfe_pn({{ }});
+ }
+ 0x15,0x1d: decode OPCODE_15 {
+ 0: ArmMacroFPAOp::ldfe_pn({{ }});
+ }
+ 0x16,0x1e: decode OPCODE_15 {
+ 0: ArmMacroFPAOp::stfe_pnw({{ }});
+ }
+ 0x17,0x1f: decode OPCODE_15 {
+ 0: ArmMacroFPAOp::ldfe_pnw({{ }});
+ }
+ }
+ 0x2: decode PUNWL {
+ // could really just decode as a single instruction
+ 0x00,0x04,0x08,0x0c: ArmMacroFMOp::sfm_({{ }});
+ 0x01,0x05,0x09,0x0d: ArmMacroFMOp::lfm_({{ }});
+ 0x02,0x06,0x0a,0x0e: ArmMacroFMOp::sfm_w({{ }});
+ 0x03,0x07,0x0b,0x0f: ArmMacroFMOp::lfm_w({{ }});
+ 0x10,0x14,0x18,0x1c: ArmMacroFMOp::sfm_p({{ }});
+ 0x11,0x15,0x19,0x1d: ArmMacroFMOp::lfm_p({{ }});
+ 0x12,0x16,0x1a,0x1e: ArmMacroFMOp::sfm_pw({{ }});
+ 0x13,0x17,0x1b,0x1f: ArmMacroFMOp::lfm_pw({{ }});
+ }
+ }
+ 0x7: decode OPCODE_24 {
+ 0: decode CPNUM {
+ // Coprocessor Instructions
+ 0x1: decode OPCODE_4 {
+ format FloatOp {
+ // Basic FPA Instructions
+ 0: decode OPCODE_23_20 {
+ 0x0: decode OPCODE_15 {
+ 0: adf({{ Fd.sf = Fn.sf + Fm.sf; }});
+ 1: mvf({{ Fd.sf = Fm.sf; }});
+ }
+ 0x1: decode OPCODE_15 {
+ 0: muf({{ Fd.sf = Fn.sf * Fm.sf; }});
+ 1: mnf({{ Fd.sf = -Fm.sf; }});
+ }
+ 0x2: decode OPCODE_15 {
+ 0: suf({{ Fd.sf = Fn.sf - Fm.sf; }});
+ 1: abs({{ Fd.sf = fabs(Fm.sf); }});
+ }
+ 0x3: decode OPCODE_15 {
+ 0: rsf({{ Fd.sf = Fm.sf - Fn.sf; }});
+ 1: rnd({{ Fd.sf = rint(Fm.sf); }});
+ }
+ 0x4: decode OPCODE_15 {
+ 0: dvf({{ Fd.sf = Fn.sf / Fm.sf; }});
+ 1: sqt({{ Fd.sf = sqrt(Fm.sf); }});
+ }
+ 0x5: decode OPCODE_15 {
+ 0: rdf({{ Fd.sf = Fm.sf / Fn.sf; }});
+ 1: log({{ Fd.sf = log10(Fm.sf); }});
+ }
+ 0x6: decode OPCODE_15 {
+ 0: pow({{ Fd.sf = pow(Fm.sf, Fn.sf); }});
+ 1: lgn({{ Fd.sf = log(Fm.sf); }});
+ }
+ 0x7: decode OPCODE_15 {
+ 0: rpw({{ Fd.sf = pow(Fn.sf, Fm.sf); }});
+ 1: exp({{ Fd.sf = exp(Fm.sf); }});
+ }
+ 0x8: decode OPCODE_15 {
+ 0: rmf({{ Fd.sf = drem(Fn.sf, Fm.sf); }});
+ 1: sin({{ Fd.sf = sin(Fm.sf); }});
+ }
+ 0x9: decode OPCODE_15 {
+ 0: fml({{ Fd.sf = Fn.sf * Fm.sf; }});
+ 1: cos({{ Fd.sf = cos(Fm.sf); }});
+ }
+ 0xa: decode OPCODE_15 {
+ 0: fdv({{ Fd.sf = Fn.sf / Fm.sf; }});
+ 1: tan({{ Fd.sf = tan(Fm.sf); }});
+ }
+ 0xb: decode OPCODE_15 {
+ 0: frd({{ Fd.sf = Fm.sf / Fn.sf; }});
+ 1: asn({{ Fd.sf = asin(Fm.sf); }});
+ }
+ 0xc: decode OPCODE_15 {
+ 0: pol({{ Fd.sf = atan2(Fn.sf, Fm.sf); }});
+ 1: acs({{ Fd.sf = acos(Fm.sf); }});
+ }
+ 0xd: decode OPCODE_15 {
+ 1: atn({{ Fd.sf = atan(Fm.sf); }});
+ }
+ 0xe: decode OPCODE_15 {
+ // Unnormalised Round
+ 1: FailUnimpl::urd();
+ }
+ 0xf: decode OPCODE_15 {
+ // Normalise
+ 1: FailUnimpl::nrm();
+ }
+ }
+ 1: decode OPCODE_15_12 {
+ 0xf: decode OPCODE_23_21 {
+ format FloatCmp {
+ 0x4: cmf({{ Fn.df }}, {{ Fm.df }});
+ 0x5: cnf({{ Fn.df }}, {{ -Fm.df }});
+ 0x6: cmfe({{ Fn.df }}, {{ Fm.df}});
+ 0x7: cnfe({{ Fn.df }}, {{ -Fm.df}});
+ }
+ }
+ default: decode OPCODE_23_20 {
+ 0x0: decode OPCODE_7 {
+ 0: flts({{ Fn.sf = (float) Rd.sw; }});
+ 1: fltd({{ Fn.df = (double) Rd.sw; }});
+ }
+ 0x1: decode OPCODE_7 {
+ 0: fixs({{ Rd = (uint32_t) Fm.sf; }});
+ 1: fixd({{ Rd = (uint32_t) Fm.df; }});
+ }
+ 0x2: wfs({{ Fpsr = Rd; }});
+ 0x3: rfs({{ Rd = Fpsr; }});
+ 0x4: FailUnimpl::wfc();
+ 0x5: FailUnimpl::rfc();
+ }
+ }
+ }
+ }
+ }
+ format PredOp {
+ // ARM System Call (SoftWare Interrupt)
+ 1: swi({{ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR),
+ condCode))
+ {
+ //xc->syscall(R7);
+ xc->syscall(IMMED_23_0);
+ }
+ }});
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/arch/arm/isa/formats/basic.isa b/src/arch/arm/isa/formats/basic.isa
new file mode 100644
index 000000000..d154b987c
--- /dev/null
+++ b/src/arch/arm/isa/formats/basic.isa
@@ -0,0 +1,103 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+// Basic instruction class declaration template.
+def template BasicDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ /// Constructor.
+ %(class_name)s(MachInst machInst);
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+
+// Basic instruction class execute method template.
+def template BasicExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+// Basic decode template.
+def template BasicDecode {{
+ return new %(class_name)s(machInst);
+}};
+
+// Basic decode template, passing mnemonic in as string arg to constructor.
+def template BasicDecodeWithMnemonic {{
+ return new %(class_name)s("%(mnemonic)s", machInst);
+}};
+
+// Definitions of execute methods that panic.
+def template BasicExecPanic {{
+Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+{
+ panic("Execute method called when it shouldn't!");
+}
+}};
+
+// The most basic instruction format...
+def format BasicOp(code, *flags) {{
+ iop = InstObjParams(name, Name, 'ArmStaticInst', code, flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa
new file mode 100644
index 000000000..40aa4a952
--- /dev/null
+++ b/src/arch/arm/isa/formats/branch.isa
@@ -0,0 +1,307 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Control transfer instructions
+//
+
+output header {{
+
+#include <iostream>
+
+ /**
+ * Base class for instructions whose disassembly is not purely a
+ * function of the machine instruction (i.e., it depends on the
+ * PC). This class overrides the disassemble() method to check
+ * the PC and symbol table values before re-using a cached
+ * disassembly string. This is necessary for branches and jumps,
+ * where the disassembly string includes the target address (which
+ * may depend on the PC and/or symbol table).
+ */
+ class PCDependentDisassembly : public PredOp
+ {
+ protected:
+ /// Cached program counter from last disassembly
+ mutable Addr cachedPC;
+
+ /// Cached symbol table pointer from last disassembly
+ mutable const SymbolTable *cachedSymtab;
+
+ /// Constructor
+ PCDependentDisassembly(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : PredOp(mnem, _machInst, __opClass),
+ cachedPC(0), cachedSymtab(0)
+ {
+ }
+
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branches (PC-relative control transfers),
+ * conditional or unconditional.
+ */
+ class Branch : public PCDependentDisassembly
+ {
+ protected:
+ /// target address (signed) Displacement .
+ int32_t disp;
+
+ /// Constructor.
+ Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(OFFSET << 2)
+ {
+ //If Bit 26 is 1 then Sign Extend
+ if ( (disp & 0x02000000) > 0 ) {
+ disp |= 0xFC000000;
+ }
+ }
+
+ Addr branchTarget(Addr branchPC) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branch and exchange instructions on the ARM
+ */
+ class BranchExchange : public PredOp
+ {
+ protected:
+ /// Constructor
+ BranchExchange(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : PredOp(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+
+ /**
+ * Base class for jumps (register-indirect control transfers). In
+ * the Arm ISA, these are always unconditional.
+ */
+ class Jump : public PCDependentDisassembly
+ {
+ protected:
+
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ uint32_t target;
+
+ public:
+ /// Constructor
+ Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(OFFSET << 2)
+ {
+ }
+
+ Addr branchTarget(ThreadContext *tc) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ Addr
+ Branch::branchTarget(Addr branchPC) const
+ {
+ return branchPC + 8 + disp;
+ }
+
+ Addr
+ Jump::branchTarget(ThreadContext *tc) const
+ {
+ Addr NPC = tc->readPC() + 8;
+ uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
+ return (Rb & ~3) | (NPC & 1);
+ }
+
+ const std::string &
+ PCDependentDisassembly::disassemble(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ if (!cachedDisassembly ||
+ pc != cachedPC || symtab != cachedSymtab)
+ {
+ if (cachedDisassembly)
+ delete cachedDisassembly;
+
+ cachedDisassembly =
+ new std::string(generateDisassembly(pc, symtab));
+ cachedPC = pc;
+ cachedSymtab = symtab;
+ }
+
+ return *cachedDisassembly;
+ }
+
+ std::string
+ Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ Addr target = pc + 8 + disp;
+
+ std::string str;
+ if (symtab && symtab->findSymbol(target, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", target);
+
+ return ss.str();
+ }
+
+ std::string
+ BranchExchange::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+
+ std::string
+ Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ return ss.str();
+ }
+}};
+
+def format Branch(code,*opt_flags) {{
+
+ #Build Instruction Flags
+ #Use Link & Likely Flags to Add Link/Condition Code
+ inst_flags = ('IsDirectControl', )
+ for x in opt_flags:
+ if x == 'Link':
+ code += 'LR = NPC;\n'
+ else:
+ inst_flags += (x, )
+
+ #Take into account uncond. branch instruction
+ if 'cond == 1' in code:
+ inst_flags += ('IsUnCondControl', )
+ else:
+ inst_flags += ('IsCondControl', )
+
+ icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n'
+ icode += code
+ icode += ' NPC = NPC + 4 + disp;\n'
+ icode += '} else {\n'
+ icode += ' NPC = NPC;\n'
+ icode += '};\n'
+
+ code = icode
+
+ iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+def format BranchExchange(code,*opt_flags) {{
+ #Build Instruction Flags
+ #Use Link & Likely Flags to Add Link/Condition Code
+ inst_flags = ('IsIndirectControl', )
+ for x in opt_flags:
+ if x == 'Link':
+ code += 'LR = NPC;\n'
+ else:
+ inst_flags += (x, )
+
+ #Take into account uncond. branch instruction
+ if 'cond == 1' in code:
+ inst_flags += ('IsUnCondControl', )
+ else:
+ inst_flags += ('IsCondControl', )
+
+ #Condition code
+
+ icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n'
+ icode += code
+ icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n'
+ icode += '} else {\n'
+ icode += ' NPC = NPC;\n'
+ icode += '};\n'
+
+ code = icode
+
+ iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+def format Jump(code, *opt_flags) {{
+ #Build Instruction Flags
+ #Use Link Flag to Add Link Code
+ inst_flags = ('IsIndirectControl', 'IsUncondControl')
+ for x in opt_flags:
+ if x == 'Link':
+ code = 'LR = NPC;\n' + code
+ elif x == 'ClearHazards':
+ code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
+ else:
+ inst_flags += (x, )
+
+ iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+ #exec_output = PredOpExecute.subst(iop)
+}};
+
+
diff --git a/src/arch/arm/isa/formats/formats.isa b/src/arch/arm/isa/formats/formats.isa
new file mode 100644
index 000000000..5f6faa741
--- /dev/null
+++ b/src/arch/arm/isa/formats/formats.isa
@@ -0,0 +1,57 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+//Templates from this format are used later
+//Include the basic format
+##include "basic.isa"
+
+//Include support for predicated instructions
+##include "pred.isa"
+
+//Include utility functions
+##include "util.isa"
+
+//Include the float formats
+##include "fp.isa"
+
+//Include the mem format
+##include "mem.isa"
+
+//Include the macro-mem format
+##include "macromem.isa"
+
+//Include the branch format
+##include "branch.isa"
+
+//Include the unimplemented format
+##include "unimp.isa"
+
+//Include the unknown format
+##include "unknown.isa"
diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa
new file mode 100644
index 000000000..682c76079
--- /dev/null
+++ b/src/arch/arm/isa/formats/fp.isa
@@ -0,0 +1,150 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Floating Point operate instructions
+//
+
+output header {{
+
+ /**
+ * Base class for FP operations.
+ */
+ class FPAOp : public PredOp
+ {
+ protected:
+
+ /// Constructor
+ FPAOp(const char *mnem, MachInst _machInst, OpClass __opClass) : PredOp(mnem, _machInst, __opClass)
+ {
+ }
+
+ //std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+}};
+
+output exec {{
+}};
+
+def template FPAExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+
+ %(op_decl)s;
+ %(op_rd)s;
+
+ %(code)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode) &&
+ fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template FloatDoubleDecode {{
+ {
+ ArmStaticInst *i = NULL;
+ switch (OPCODE_19 << 1 | OPCODE_7)
+ {
+ case 0:
+ i = (ArmStaticInst *)new %(class_name)sS(machInst);
+ break;
+ case 1:
+ i = (ArmStaticInst *)new %(class_name)sD(machInst);
+ break;
+ case 2:
+ case 3:
+ default:
+ panic("Cannot decode float/double nature of the instruction");
+ }
+ return i;
+ }
+}};
+
+// Primary format for float point operate instructions:
+def format FloatOp(code, *flags) {{
+ orig_code = code
+
+ cblk = code
+ iop = InstObjParams(name, Name, 'FPAOp', cblk, flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = FPAExecute.subst(iop)
+
+ sng_cblk = code
+ sng_iop = InstObjParams(name, Name+'S', 'FPAOp', sng_cblk, flags)
+ header_output += BasicDeclare.subst(sng_iop)
+ decoder_output += BasicConstructor.subst(sng_iop)
+ exec_output += FPAExecute.subst(sng_iop)
+
+ dbl_code = re.sub(r'\.sf', '.df', orig_code)
+
+ dbl_cblk = dbl_code
+ dbl_iop = InstObjParams(name, Name+'D', 'FPAOp', dbl_cblk, flags)
+ header_output += BasicDeclare.subst(dbl_iop)
+ decoder_output += BasicConstructor.subst(dbl_iop)
+ exec_output += FPAExecute.subst(dbl_iop)
+
+ decode_block = FloatDoubleDecode.subst(iop)
+}};
+
+let {{
+ calcFPCcCode = '''
+ uint16_t _in, _iz, _ic, _iv;
+
+ _in = %(fReg1)s < %(fReg2)s;
+ _iz = %(fReg1)s == %(fReg2)s;
+ _ic = %(fReg1)s >= %(fReg2)s;
+ _iv = (isnan(%(fReg1)s) || isnan(%(fReg2)s)) & 1;
+
+ Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
+ (Cpsr & 0x0FFFFFFF);
+ '''
+}};
+
+def format FloatCmp(fReg1, fReg2, *flags) {{
+ code = calcFPCcCode % vars()
+ iop = InstObjParams(name, Name, 'FPAOp', code, flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = FPAExecute.subst(iop)
+}};
+
+
diff --git a/src/arch/arm/isa/formats/macromem.isa b/src/arch/arm/isa/formats/macromem.isa
new file mode 100644
index 000000000..bc055d74e
--- /dev/null
+++ b/src/arch/arm/isa/formats/macromem.isa
@@ -0,0 +1,389 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Macro Memory-format instructions
+//
+
+output header {{
+
+ /**
+ * Arm Macro Memory operations like LDM/STM
+ */
+ class ArmMacroMemoryOp : public PredMacroOp
+ {
+ protected:
+ /// Memory request flags. See mem_req_base.hh.
+ unsigned memAccessFlags;
+ /// Pointer to EAComp object.
+ const StaticInstPtr eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr memAccPtr;
+
+ uint32_t reglist;
+ uint32_t ones;
+ uint32_t puswl,
+ prepost,
+ up,
+ psruser,
+ writeback,
+ loadop;
+
+ ArmMacroMemoryOp(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : PredMacroOp(mnem, _machInst, __opClass),
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
+ reglist(REGLIST), ones(0), puswl(PUSWL), prepost(PREPOST), up(UP),
+ psruser(PSRUSER), writeback(WRITEBACK), loadop(LOADOP)
+ {
+ ones = number_of_ones(reglist);
+ numMicroops = ones + writeback + 1;
+ // Remember that writeback adds a uop
+ microOps = new StaticInstPtr[numMicroops];
+ }
+ };
+
+ /**
+ * Arm Macro FPA operations to fix ldfd and stfd instructions
+ */
+ class ArmMacroFPAOp : public PredMacroOp
+ {
+ protected:
+ uint32_t puswl,
+ prepost,
+ up,
+ psruser,
+ writeback,
+ loadop;
+ int32_t disp8;
+
+ ArmMacroFPAOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PredMacroOp(mnem, _machInst, __opClass),
+ puswl(PUSWL), prepost(PREPOST), up(UP),
+ psruser(PSRUSER), writeback(WRITEBACK), loadop(LOADOP),
+ disp8(IMMED_7_0 << 2)
+ {
+ numMicroops = 3 + writeback;
+ microOps = new StaticInstPtr[numMicroops];
+ }
+ };
+
+ /**
+ * Arm Macro FM operations to fix lfm and sfm
+ */
+ class ArmMacroFMOp : public PredMacroOp
+ {
+ protected:
+ uint32_t punwl,
+ prepost,
+ up,
+ n1bit,
+ writeback,
+ loadop,
+ n0bit,
+ count;
+ int32_t disp8;
+
+ ArmMacroFMOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PredMacroOp(mnem, _machInst, __opClass),
+ punwl(PUNWL), prepost(PREPOST), up(UP),
+ n1bit(OPCODE_22), writeback(WRITEBACK), loadop(LOADOP),
+ n0bit(OPCODE_15), disp8(IMMED_7_0 << 2)
+ {
+ // Transfer 1-4 registers based on n1 and n0 bits (with 00 repr. 4)
+ count = (n1bit << 1) | n0bit;
+ if (count == 0)
+ count = 4;
+ numMicroops = (3*count) + writeback;
+ microOps = new StaticInstPtr[numMicroops];
+ }
+ };
+
+
+}};
+
+
+output decoder {{
+}};
+
+def template MacroStoreDeclare {{
+ /**
+ * Static instructions class for a store multiple instruction
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ // Constructor
+ %(class_name)s(MachInst machInst);
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MacroStoreConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ uint32_t regs_to_handle = reglist;
+ uint32_t j = 0,
+ start_addr = 0,
+ end_addr = 0;
+
+ switch (puswl)
+ {
+ case 0x01: // L ldmda_l
+ start_addr = (ones << 2) - 4;
+ end_addr = 0;
+ break;
+ case 0x03: // WL ldmda_wl
+ start_addr = (ones << 2) - 4;
+ end_addr = 0;
+ break;
+ case 0x08: // U stmia_u
+ start_addr = 0;
+ end_addr = (ones << 2) - 4;
+ break;
+ case 0x09: // U L ldmia_ul
+ start_addr = 0;
+ end_addr = (ones << 2) - 4;
+ break;
+ case 0x0b: // U WL ldmia
+ start_addr = 0;
+ end_addr = (ones << 2) - 4;
+ break;
+ case 0x11: // P L ldmdb
+ start_addr = (ones << 2); // U-bit is already 0 for subtract
+ end_addr = 4; // negative 4
+ break;
+ case 0x12: // P W stmdb
+ start_addr = (ones << 2); // U-bit is already 0 for subtract
+ end_addr = 4; // negative 4
+ break;
+ case 0x18: // PU stmib
+ start_addr = 4;
+ end_addr = (ones << 2) + 4;
+ break;
+ case 0x19: // PU L ldmib
+ start_addr = 4;
+ end_addr = (ones << 2) + 4;
+ break;
+ default:
+ panic("Unhandled Load/Store Multiple Instruction");
+ break;
+ }
+
+ //TODO - Add addi_uop/subi_uop here to create starting addresses
+ //Just using addi with 0 offset makes a "copy" of Rn for our use
+ uint32_t newMachInst = 0;
+ newMachInst = machInst & 0xffff0000;
+ microOps[0] = new Addi_uop(newMachInst);
+
+ for (int i = 1; i < ones+1; i++)
+ {
+ // Get next available bit for transfer
+ while (! ( regs_to_handle & (1<<j)))
+ j++;
+ regs_to_handle &= ~(1<<j);
+
+ microOps[i] = gen_ldrstr_uop(machInst, loadop, j, start_addr);
+
+ if (up)
+ start_addr += 4;
+ else
+ start_addr -= 4;
+ }
+
+ /* TODO: Take a look at how these 2 values should meet together
+ if (start_addr != (end_addr - 4))
+ {
+ fprintf(stderr, "start_addr: %d\n", start_addr);
+ fprintf(stderr, "end_addr: %d\n", end_addr);
+ panic("start_addr does not meet end_addr");
+ }
+ */
+
+ if (writeback)
+ {
+ uint32_t newMachInst = machInst & 0xf0000000;
+ uint32_t rn = (machInst >> 16) & 0x0f;
+ // 3322 2222 2222 1111 1111 11
+ // 1098 7654 3210 9876 5432 1098 7654 3210
+ // COND 0010 0100 [RN] [RD] 0000 [ IMM ]
+ // sub rn, rn, imm
+ newMachInst |= 0x02400000;
+ newMachInst |= ((rn << 16) | (rn << 12));
+ newMachInst |= (ones << 2);
+ if (up)
+ {
+ microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
+ }
+ else
+ {
+ microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
+ }
+ }
+ microOps[numMicroops-1]->setLastMicroop();
+ }
+
+}};
+
+def template MacroStoreExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+ if (fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template MacroFPAConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+
+ uint32_t start_addr = 0;
+
+ if (prepost)
+ start_addr = disp8;
+ else
+ start_addr = 0;
+
+ emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr);
+
+ if (writeback)
+ {
+ uint32_t newMachInst = machInst & 0xf0000000;
+ uint32_t rn = (machInst >> 16) & 0x0f;
+ // 3322 2222 2222 1111 1111 11
+ // 1098 7654 3210 9876 5432 1098 7654 3210
+ // COND 0010 0100 [RN] [RD] 0000 [ IMM ]
+ // sub rn, rn, imm
+ newMachInst |= 0x02400000;
+ newMachInst |= ((rn << 16) | (rn << 12));
+ if (up)
+ {
+ newMachInst |= disp8;
+ microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
+ }
+ else
+ {
+ newMachInst |= disp8;
+ microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
+ }
+ }
+ microOps[numMicroops-1]->setLastMicroop();
+ }
+
+}};
+
+
+def template MacroFMConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+
+ uint32_t start_addr = 0;
+
+ if (prepost)
+ start_addr = disp8;
+ else
+ start_addr = 0;
+
+ for (int i = 0; i < count; i++)
+ {
+ emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr);
+ }
+
+ if (writeback)
+ {
+ uint32_t newMachInst = machInst & 0xf0000000;
+ uint32_t rn = (machInst >> 16) & 0x0f;
+ // 3322 2222 2222 1111 1111 11
+ // 1098 7654 3210 9876 5432 1098 7654 3210
+ // COND 0010 0100 [RN] [RD] 0000 [ IMM ]
+ // sub rn, rn, imm
+ newMachInst |= 0x02400000;
+ newMachInst |= ((rn << 16) | (rn << 12));
+ if (up)
+ {
+ newMachInst |= disp8;
+ microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
+ }
+ else
+ {
+ newMachInst |= disp8;
+ microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
+ }
+ }
+ microOps[numMicroops-1]->setLastMicroop();
+ }
+
+}};
+
+
+def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
+ iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
+ header_output = MacroStoreDeclare.subst(iop)
+ decoder_output = MacroStoreConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = MacroStoreExecute.subst(iop)
+}};
+
+def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
+ iop = InstObjParams(name, Name, 'ArmMacroFPAOp', code, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = MacroFPAConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = PredOpExecute.subst(iop)
+}};
+
+def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
+ iop = InstObjParams(name, Name, 'ArmMacroFMOp', code, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = MacroFMConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = PredOpExecute.subst(iop)
+}};
+
+
+
diff --git a/src/arch/arm/isa/formats/mem.isa b/src/arch/arm/isa/formats/mem.isa
new file mode 100644
index 000000000..0c736f947
--- /dev/null
+++ b/src/arch/arm/isa/formats/mem.isa
@@ -0,0 +1,593 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Memory-format instructions
+//
+
+output header {{
+ /**
+ * Base class for general Arm memory-format instructions.
+ */
+ class Memory : public PredOp
+ {
+ protected:
+
+ /// Memory request flags. See mem_req_base.hh.
+ unsigned memAccessFlags;
+ /// Pointer to EAComp object.
+ const StaticInstPtr eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr memAccPtr;
+
+ /// Displacement for EA calculation (signed).
+ int32_t disp;
+ int32_t disp8;
+ int32_t up;
+ int32_t hilo,
+ shift_size,
+ shift;
+
+ /// Constructor
+ Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : PredOp(mnem, _machInst, __opClass),
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
+ disp(IMMED_11_0), disp8(IMMED_7_0 << 2), up(UP),
+ hilo((IMMED_HI_11_8 << 4) | IMMED_LO_3_0),
+ shift_size(SHIFT_SIZE), shift(SHIFT)
+ {
+ // When Up is not set, then we must subtract by the displacement
+ if (!up)
+ {
+ disp = -disp;
+ disp8 = -disp8;
+ hilo = -hilo;
+ }
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ public:
+
+ const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
+ const StaticInstPtr &memAccInst() const { return memAccPtr; }
+ };
+
+ /**
+ * Base class for a few miscellaneous memory-format insts
+ * that don't interpret the disp field
+ */
+ class MemoryNoDisp : public Memory
+ {
+ protected:
+ /// Constructor
+ MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+
+output decoder {{
+ std::string
+ Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s", mnemonic);
+ }
+
+ std::string
+ MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s", mnemonic);
+ }
+}};
+
+def template LoadStoreDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ protected:
+
+ /**
+ * "Fake" effective address computation class for "%(mnemonic)s".
+ */
+ class EAComp : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ EAComp(MachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ /**
+ * "Fake" memory access instruction class for "%(mnemonic)s".
+ */
+ class MemAcc : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ MemAcc(MachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ public:
+
+ /// Constructor.
+ %(class_name)s(MachInst machInst);
+
+ %(BasicExecDeclare)s
+
+ %(InitiateAccDeclare)s
+
+ %(CompleteAccDeclare)s
+ };
+}};
+
+
+def template InitiateAccDeclare {{
+ Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+
+def template CompleteAccDeclare {{
+ Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+
+def template EACompConstructor {{
+ inline %(class_name)s::EAComp::EAComp(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
+ {
+ %(constructor)s;
+ }
+}};
+
+
+def template MemAccConstructor {{
+ inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+
+def template LoadStoreConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+ new EAComp(machInst), new MemAcc(machInst))
+ {
+ %(constructor)s;
+ }
+}};
+
+
+def template EACompExecute {{
+ Fault
+ %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ %(op_wb)s;
+ xc->setEA(EA);
+ }
+ }
+
+ return fault;
+ }
+}};
+
+def template LoadMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_src_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
+ }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadCompleteAcc {{
+ Fault %(class_name)s::completeAcc(PacketPtr pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ // ARM instructions will not have a pkt if the predicate is false
+ Mem = pkt->get<typeof(Mem)>();
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, NULL);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, NULL);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+ }
+
+ return fault;
+ }
+}};
+
+def template StoreInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, NULL);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ // Need to write back any potential address register update
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreCompleteAcc {{
+ Fault %(class_name)s::completeAcc(PacketPtr pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_dest_decl)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+ }
+
+ return fault;
+ }
+}};
+
+def template StoreCondCompleteAcc {{
+ Fault %(class_name)s::completeAcc(PacketPtr pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_dest_decl)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template MiscMemAccExecute {{
+ Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+ }
+
+ return NoFault;
+ }
+}};
+
+def template MiscExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+ }
+
+ return NoFault;
+ }
+}};
+
+def template MiscInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("Misc instruction does not support split access method!");
+ return NoFault;
+ }
+}};
+
+
+def template MiscCompleteAcc {{
+ Fault %(class_name)s::completeAcc(PacketPtr pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("Misc instruction does not support split access method!");
+
+ return NoFault;
+ }
+}};
+
+def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ ea_code = ArmGenericCodeSubs(ea_code)
+ memacc_code = ArmGenericCodeSubs(memacc_code)
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = BasicDecode,
+ exec_template_base = 'Load')
+}};
+
+def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ ea_code = ArmGenericCodeSubs(ea_code)
+ memacc_code = ArmGenericCodeSubs(memacc_code)
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ exec_template_base = 'Store')
+}};
+
diff --git a/src/arch/arm/isa/formats/pred.isa b/src/arch/arm/isa/formats/pred.isa
new file mode 100644
index 000000000..1e9dba07e
--- /dev/null
+++ b/src/arch/arm/isa/formats/pred.isa
@@ -0,0 +1,402 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Predicated Instruction Execution
+//
+
+output header {{
+#include <iostream>
+
+ enum ArmPredicateBits {
+ COND_EQ = 0,
+ COND_NE, // 1
+ COND_CS, // 2
+ COND_CC, // 3
+ COND_MI, // 4
+ COND_PL, // 5
+ COND_VS, // 6
+ COND_VC, // 7
+ COND_HI, // 8
+ COND_LS, // 9
+ COND_GE, // 10
+ COND_LT, // 11
+ COND_GT, // 12
+ COND_LE, // 13
+ COND_AL, // 14
+ COND_NV // 15
+ };
+
+ inline uint32_t
+ rotate_imm(uint32_t immValue, uint32_t rotateValue)
+ {
+ return ((immValue >> (int)(rotateValue & 31)) |
+ (immValue << (32 - (int)(rotateValue & 31))));
+ }
+
+ inline uint32_t nSet(uint32_t cpsr) { return cpsr & (1<<31); }
+ inline uint32_t zSet(uint32_t cpsr) { return cpsr & (1<<30); }
+ inline uint32_t cSet(uint32_t cpsr) { return cpsr & (1<<29); }
+ inline uint32_t vSet(uint32_t cpsr) { return cpsr & (1<<28); }
+
+ inline bool arm_predicate(uint32_t cpsr, uint32_t predBits)
+ {
+
+ enum ArmPredicateBits armPredBits = (enum ArmPredicateBits) predBits;
+ uint32_t result = 0;
+ switch (armPredBits)
+ {
+ case COND_EQ:
+ result = zSet(cpsr); break;
+ case COND_NE:
+ result = !zSet(cpsr); break;
+ case COND_CS:
+ result = cSet(cpsr); break;
+ case COND_CC:
+ result = !cSet(cpsr); break;
+ case COND_MI:
+ result = nSet(cpsr); break;
+ case COND_PL:
+ result = !nSet(cpsr); break;
+ case COND_VS:
+ result = vSet(cpsr); break;
+ case COND_VC:
+ result = !vSet(cpsr); break;
+ case COND_HI:
+ result = cSet(cpsr) && !zSet(cpsr); break;
+ case COND_LS:
+ result = !cSet(cpsr) || zSet(cpsr); break;
+ case COND_GE:
+ result = (!nSet(cpsr) && !vSet(cpsr)) || (nSet(cpsr) && vSet(cpsr)); break;
+ case COND_LT:
+ result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)); break;
+ case COND_GT:
+ result = (!nSet(cpsr) && !vSet(cpsr) && !zSet(cpsr)) || (nSet(cpsr) && vSet(cpsr) && !zSet(cpsr)); break;
+ case COND_LE:
+ result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)) || zSet(cpsr); break;
+ case COND_AL: result = 1; break;
+ case COND_NV: result = 0; break;
+ default:
+ fprintf(stderr, "Unhandled predicate condition: %d\n", armPredBits);
+ exit(1);
+ }
+ if (result)
+ return true;
+ else
+ return false;
+ }
+
+
+ /**
+ * Base class for predicated integer operations.
+ */
+ class PredOp : public ArmStaticInst
+ {
+ protected:
+
+ uint32_t condCode;
+
+ /// Constructor
+ PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ ArmStaticInst(mnem, _machInst, __opClass),
+ condCode(COND_CODE)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for predicated immediate operations.
+ */
+ class PredImmOp : public PredOp
+ {
+ protected:
+
+ uint32_t imm;
+ uint32_t rotate;
+ uint32_t rotated_imm;
+ uint32_t rotated_carry;
+
+ /// Constructor
+ PredImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ PredOp(mnem, _machInst, __opClass),
+ imm(IMM), rotate(ROTATE << 1), rotated_imm(0),
+ rotated_carry(0)
+ {
+ rotated_imm = rotate_imm(imm, rotate);
+ if (rotate != 0)
+ rotated_carry = (rotated_imm >> 31) & 1;
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for predicated integer operations.
+ */
+ class PredIntOp : public PredOp
+ {
+ protected:
+
+ uint32_t shift_size;
+ uint32_t shift;
+
+ /// Constructor
+ PredIntOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ PredOp(mnem, _machInst, __opClass),
+ shift_size(SHIFT_SIZE), shift(SHIFT)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for predicated macro-operations.
+ */
+ class PredMacroOp : public PredOp
+ {
+ protected:
+
+ uint32_t numMicroops;
+ StaticInstPtr * microOps;
+
+ /// Constructor
+ PredMacroOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ PredOp(mnem, _machInst, __opClass),
+ numMicroops(0)
+ {
+ // We rely on the subclasses of this object to handle the
+ // initialization of the micro-operations, since they are
+ // all of variable length
+ flags[IsMacroop] = true;
+ }
+
+ ~PredMacroOp()
+ {
+ if (numMicroops)
+ delete [] microOps;
+ }
+
+ StaticInstPtr fetchMicroop(MicroPC microPC)
+ {
+ assert(microPC < numMicroops);
+ return microOps[microPC];
+ }
+
+ %(BasicExecPanic)s
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for predicated micro-operations.
+ */
+ class PredMicroop : public PredOp
+ {
+ /// Constructor
+ PredMicroop(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ PredOp(mnem, _machInst, __opClass)
+ {
+ flags[IsMicroop] = true;
+ }
+ };
+
+}};
+
+def template PredOpExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
+ {
+ if (fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+ }
+ else
+ return NoFault;
+ // Predicated false instructions should not return faults
+
+ return fault;
+ }
+}};
+
+//Outputs to decoder.cc
+output decoder {{
+ std::string PredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ ss << ", ";
+
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ", ";
+ }
+
+ return ss.str();
+ }
+
+ std::string PredImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ ss << ", ";
+
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ", ";
+ }
+
+ return ss.str();
+ }
+
+ std::string PredIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ ss << ", ";
+
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ", ";
+ }
+
+ return ss.str();
+ }
+
+ std::string PredMacroOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ return ss.str();
+ }
+
+}};
+
+let {{
+
+ calcCcCode = '''
+ uint16_t _ic, _iv, _iz, _in;
+
+ _in = (resTemp >> 31) & 1;
+ _iz = (resTemp == 0);
+ _iv = %(ivValue)s & 1;
+ _ic = %(icValue)s & 1;
+
+ Cpsr = _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
+ (Cpsr & 0x0FFFFFFF);
+
+ DPRINTF(Arm, "in = %%d\\n", _in);
+ DPRINTF(Arm, "iz = %%d\\n", _iz);
+ DPRINTF(Arm, "ic = %%d\\n", _ic);
+ DPRINTF(Arm, "iv = %%d\\n", _iv);
+ '''
+
+}};
+
+def format PredOp(code, *opt_flags) {{
+ iop = InstObjParams(name, Name, 'PredOp', code, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = PredOpExecute.subst(iop)
+}};
+
+def format PredImmOp(code, *opt_flags) {{
+ iop = InstObjParams(name, Name, 'PredImmOp', code, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = PredOpExecute.subst(iop)
+}};
+
+def format PredImmOpCc(code, icValue, ivValue, *opt_flags) {{
+ ccCode = calcCcCode % vars()
+ code += ccCode;
+ iop = InstObjParams(name, Name, 'PredImmOp',
+ {"code": code, "cc_code": ccCode}, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = PredOpExecute.subst(iop)
+}};
+
+def format PredIntOp(code, *opt_flags) {{
+ new_code = ArmGenericCodeSubs(code)
+ iop = InstObjParams(name, Name, 'PredIntOp', new_code, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = PredOpExecute.subst(iop)
+}};
+
+def format PredIntOpCc(code, icValue, ivValue, *opt_flags) {{
+ ccCode = calcCcCode % vars()
+ code += ccCode;
+ new_code = ArmGenericCodeSubs(code)
+ iop = InstObjParams(name, Name, 'PredIntOp',
+ {"code": new_code, "cc_code": ccCode }, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = PredOpExecute.subst(iop)
+}};
+
diff --git a/src/arch/arm/isa/formats/unimp.isa b/src/arch/arm/isa/formats/unimp.isa
new file mode 100644
index 000000000..c82bb41c6
--- /dev/null
+++ b/src/arch/arm/isa/formats/unimp.isa
@@ -0,0 +1,144 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Unimplemented instructions
+//
+
+output header {{
+ /**
+ * Static instruction class for unimplemented instructions that
+ * cause simulator termination. Note that these are recognized
+ * (legal) instructions that the simulator does not support; the
+ * 'Unknown' class is used for unrecognized/illegal instructions.
+ * This is a leaf class.
+ */
+ class FailUnimplemented : public ArmStaticInst
+ {
+ public:
+ /// Constructor
+ FailUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : ArmStaticInst(_mnemonic, _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for unimplemented instructions that cause a warning
+ * to be printed (but do not terminate simulation). This
+ * implementation is a little screwy in that it will print a
+ * warning for each instance of a particular unimplemented machine
+ * instruction, not just for each unimplemented opcode. Should
+ * probably make the 'warned' flag a static member of the derived
+ * class.
+ */
+ class WarnUnimplemented : public ArmStaticInst
+ {
+ private:
+ /// Have we warned on this instruction yet?
+ mutable bool warned;
+
+ public:
+ /// Constructor
+ WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : ArmStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ FailUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (unimplemented)", mnemonic);
+ }
+
+ std::string
+ WarnUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (unimplemented)", mnemonic);
+ }
+}};
+
+output exec {{
+ Fault
+ FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unimplemented instruction '%s' "
+ "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE,
+ inst2string(machInst));
+ return new UnimplementedOpcodeFault;
+ }
+
+ Fault
+ WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (!warned) {
+ warn("\tinstruction '%s' unimplemented\n", mnemonic);
+ warned = true;
+ }
+
+ return NoFault;
+ }
+}};
+
+
+def format FailUnimpl() {{
+ iop = InstObjParams(name, 'FailUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
+def format WarnUnimpl() {{
+ iop = InstObjParams(name, 'WarnUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
diff --git a/src/arch/arm/isa/formats/unknown.isa b/src/arch/arm/isa/formats/unknown.isa
new file mode 100644
index 000000000..3d13ef616
--- /dev/null
+++ b/src/arch/arm/isa/formats/unknown.isa
@@ -0,0 +1,84 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Unknown instructions
+//
+
+output header {{
+ /**
+ * Static instruction class for unknown (illegal) instructions.
+ * These cause simulator termination if they are executed in a
+ * non-speculative mode. This is a leaf class.
+ */
+ class Unknown : public ArmStaticInst
+ {
+ public:
+ /// Constructor
+ Unknown(MachInst _machInst)
+ : ArmStaticInst("unknown", _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (inst 0x%x, opcode 0x%x, binary:%s)",
+ "unknown", machInst, OPCODE, inst2string(machInst));
+ }
+}};
+
+output exec {{
+ Fault
+ Unknown::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unknown instruction "
+ "(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst));
+ return new UnimplementedOpcodeFault;
+ }
+}};
+
+def format Unknown() {{
+ decode_block = 'return new Unknown(machInst);\n'
+}};
+
diff --git a/src/arch/arm/isa/formats/util.isa b/src/arch/arm/isa/formats/util.isa
new file mode 100644
index 000000000..ee6339c02
--- /dev/null
+++ b/src/arch/arm/isa/formats/util.isa
@@ -0,0 +1,217 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+let {{
+
+# Generic substitutions for Arm instructions
+def ArmGenericCodeSubs(code):
+ # Substitute in the shifted portion of operations
+ new_code = re.sub(r'Rm_Imm', 'shift_rm_imm(Rm, shift_size, shift, Cpsr<29:>)', code)
+ new_code = re.sub(r'Rm_Rs', 'shift_rm_rs(Rm, Rs, shift, Cpsr<29:>)', new_code)
+ new_code = re.sub(r'^', 'Cpsr = Cpsr;', new_code)
+ return new_code
+
+def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code = '', base_class = 'Memory',
+ decode_template = BasicDecode, exec_template_base = ''):
+ # Make sure flags are in lists (convert to lists if not).
+ mem_flags = makeList(mem_flags)
+ inst_flags = makeList(inst_flags)
+
+ # add hook to get effective addresses into execution trace output.
+ ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
+
+ # Some CPU models execute the memory operation as an atomic unit,
+ # while others want to separate them into an effective address
+ # computation and a memory access operation. As a result, we need
+ # to generate three StaticInst objects. Note that the latter two
+ # are nested inside the larger "atomic" one.
+
+ # Generate InstObjParams for each of the three objects. Note that
+ # they differ only in the set of code objects contained (which in
+ # turn affects the object's overall operand list).
+ iop = InstObjParams(name, Name, base_class,
+ { 'ea_code':ea_code, 'memacc_code':memacc_code, 'postacc_code':postacc_code },
+ inst_flags)
+ ea_iop = InstObjParams(name, Name, base_class,
+ { 'ea_code':ea_code },
+ inst_flags)
+ memacc_iop = InstObjParams(name, Name, base_class,
+ { 'memacc_code':memacc_code, 'postacc_code':postacc_code },
+ inst_flags)
+
+ if mem_flags:
+ s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
+ iop.constructor += s
+ memacc_iop.constructor += s
+
+ # select templates
+
+ # The InitiateAcc template is the same for StoreCond templates as the
+ # corresponding Store template..
+ StoreCondInitiateAcc = StoreInitiateAcc
+
+ memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
+ fullExecTemplate = eval(exec_template_base + 'Execute')
+ initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
+ completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
+
+ # (header_output, decoder_output, decode_block, exec_output)
+ return (LoadStoreDeclare.subst(iop),
+ EACompConstructor.subst(ea_iop)
+ + MemAccConstructor.subst(memacc_iop)
+ + LoadStoreConstructor.subst(iop),
+ decode_template.subst(iop),
+ EACompExecute.subst(ea_iop)
+ + memAccExecTemplate.subst(memacc_iop)
+ + fullExecTemplate.subst(iop)
+ + initiateAccTemplate.subst(iop)
+ + completeAccTemplate.subst(iop))
+}};
+
+
+output header {{
+ std::string inst2string(MachInst machInst);
+ StaticInstPtr gen_ldrstr_uop(uint32_t baseinst, int loadop, uint32_t rd, int32_t disp);
+ int emit_ldfstf_uops(StaticInstPtr* microOps, int index, uint32_t baseinst, int loadop, int up, int32_t disp);
+}};
+
+output decoder {{
+
+ std::string inst2string(MachInst machInst)
+ {
+ std::string str = "";
+ uint32_t mask = 0x80000000;
+
+ for(int i=0; i < 32; i++) {
+ if ((machInst & mask) == 0) {
+ str += "0";
+ } else {
+ str += "1";
+ }
+
+ mask = mask >> 1;
+ }
+
+ return str;
+ }
+
+ // Generate the bit pattern for an Ldr_uop or Str_uop;
+ StaticInstPtr
+ gen_ldrstr_uop(uint32_t baseinst, int loadop, uint32_t rd, int32_t disp)
+ {
+ StaticInstPtr newInst;
+ uint32_t newMachInst = baseinst & 0xffff0000;
+ newMachInst |= (rd << 12);
+ newMachInst |= disp;
+ if (loadop)
+ newInst = new Ldr_uop(newMachInst);
+ else
+ newInst = new Str_uop(newMachInst);
+ return newInst;
+ }
+
+ // Emits uops for a double fp move
+ int
+ emit_ldfstf_uops(StaticInstPtr* microOps, int index, uint32_t baseinst, int loadop, int up, int32_t disp)
+ {
+ StaticInstPtr newInst;
+ uint32_t newMachInst;
+
+ if (loadop)
+ {
+ newMachInst = baseinst & 0xfffff000;
+ newMachInst |= (disp & 0x0fff);
+ newInst = new Ldlo_uop(newMachInst);
+ microOps[index++] = newInst;
+
+ newMachInst = baseinst & 0xfffff000;
+ if (up)
+ newMachInst |= ((disp + 4) & 0x0fff);
+ else
+ newMachInst |= ((disp - 4) & 0x0fff);
+ newInst = new Ldhi_uop(newMachInst);
+ microOps[index++] = newInst;
+
+ newMachInst = baseinst & 0xf000f000;
+ newInst = new Mvtd_uop(newMachInst);
+ microOps[index++] = newInst;
+ }
+ else
+ {
+ newMachInst = baseinst & 0xf000f000;
+ newInst = new Mvfd_uop(newMachInst);
+ microOps[index++] = newInst;
+
+ newMachInst = baseinst & 0xfffff000;
+ newMachInst |= (disp & 0x0fff);
+ newInst = new Stlo_uop(newMachInst);
+ microOps[index++] = newInst;
+
+ newMachInst = baseinst & 0xfffff000;
+ if (up)
+ newMachInst |= ((disp + 4) & 0x0fff);
+ else
+ newMachInst |= ((disp - 4) & 0x0fff);
+ newInst = new Sthi_uop(newMachInst);
+ microOps[index++] = newInst;
+ }
+ return 3;
+ }
+
+}};
+
+output exec {{
+
+ using namespace ArmISA;
+
+ /// CLEAR ALL CPU INST/EXE HAZARDS
+ inline void
+ clear_exe_inst_hazards()
+ {
+ //CODE HERE
+ }
+
+#if FULL_SYSTEM
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ return NoFault;
+ }
+#else
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ return NoFault;
+ }
+#endif
+
+
+}};
+
+
diff --git a/src/arch/arm/isa/includes.isa b/src/arch/arm/isa/includes.isa
new file mode 100644
index 000000000..6205a8f81
--- /dev/null
+++ b/src/arch/arm/isa/includes.isa
@@ -0,0 +1,82 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "arch/arm/isa_traits.hh"
+#include "cpu/static_inst.hh"
+#include "mem/packet.hh"
+}};
+
+output decoder {{
+#include <cmath>
+#if defined(linux)
+#include <fenv.h>
+#endif
+
+#include "arch/arm/faults.hh"
+#include "arch/arm/isa_traits.hh"
+#include "arch/arm/utility.hh"
+#include "base/cprintf.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/thread_context.hh"
+
+using namespace ArmISA;
+using std::isnan;
+}};
+
+output exec {{
+#include "arch/arm/faults.hh"
+#include "arch/arm/isa_traits.hh"
+#include "arch/arm/utility.hh"
+
+#include <cmath>
+#if defined(linux)
+#include <fenv.h>
+#endif
+
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "mem/packet.hh"
+#include "mem/packet_access.hh"
+#include "sim/sim_exit.hh"
+
+using namespace ArmISA;
+using std::isnan;
+}};
+
diff --git a/src/arch/arm/isa/main.isa b/src/arch/arm/isa/main.isa
new file mode 100644
index 000000000..aeb8b69d0
--- /dev/null
+++ b/src/arch/arm/isa/main.isa
@@ -0,0 +1,63 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// ARM ISA description file.
+//
+////////////////////////////////////////////////////////////////////
+
+//Include the C++ include directives
+##include "includes.isa"
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// ArmISAInst namespace.
+//
+namespace ArmISA;
+
+//Include the utility functions
+##include "util.isa"
+
+//Include the bitfield definitions
+##include "bitfields.isa"
+
+//Include the operand_types and operand definitions
+##include "operands.isa"
+
+//Include the base class for Arm instructions, and some support code
+##include "base.isa"
+
+//Include the definitions for the instruction formats
+##include "formats/formats.isa"
+
+//Include the decoder definition
+##include "decoder.isa"
diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa
new file mode 100644
index 000000000..b2c4f8420
--- /dev/null
+++ b/src/arch/arm/isa/operands.isa
@@ -0,0 +1,72 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'sh' : ('signed int', 16),
+ 'uh' : ('unsigned int', 16),
+ 'sw' : ('signed int', 32),
+ 'uw' : ('unsigned int', 32),
+ 'ud' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64)
+}};
+
+def operands {{
+ #General Purpose Integer Reg Operands
+ 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1),
+ 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2),
+ 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3),
+ 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4),
+ 'Re': ('IntReg', 'uw', 'RE', 'IsInteger', 5),
+
+ 'Raddr': ('IntReg', 'uw', '17', 'IsInteger', 5),
+ 'R0': ('IntReg', 'uw', '0', 'IsInteger', 5),
+ 'R7': ('IntReg', 'uw', '7', 'IsInteger', 5),
+ 'Rhi': ('IntReg', 'uw', '18', 'IsInteger', 5),
+ 'Rlo': ('IntReg', 'uw', '19', 'IsInteger', 6),
+ 'LR': ('IntReg', 'uw', '14', 'IsInteger', 6),
+ 'Ignore': ('IntReg', 'uw', '16', 'IsInteger', 99),
+
+ #General Purpose Floating Point Reg Operands
+ 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 1),
+ 'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 2),
+ 'Fm': ('FloatReg', 'df', 'FM', 'IsFloating', 3),
+
+ #Memory Operand
+ 'Mem': ('Mem', 'uw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 8),
+
+ 'Cpsr': ('ControlReg', 'uw', 'CPSR', 'IsInteger', 7),
+ 'Fpsr': ('ControlReg', 'uw', 'FPSR', 'IsInteger', 7),
+ 'NPC': ('NPC', 'uw', None, (None, None, 'IsControl'), 9),
+ 'NNPC': ('NNPC', 'uw', None, (None, None, 'IsControl'), 9),
+
+}};
diff --git a/src/arch/arm/isa/util.isa b/src/arch/arm/isa/util.isa
new file mode 100644
index 000000000..4fe0d732c
--- /dev/null
+++ b/src/arch/arm/isa/util.isa
@@ -0,0 +1,282 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// 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: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Utility functions for execute methods
+//
+//
+output header {{
+
+ // Shift types for ARM instructions
+ enum ArmShiftType {
+ LSL = 0,
+ LSR,
+ ASR,
+ ROR
+ };
+
+ enum ArmShiftMode {
+ };
+
+ inline uint32_t number_of_ones(int32_t val)
+ {
+ uint32_t ones = 0;
+ for (int i = 0; i < 32; i++ )
+ {
+ if ( val & (1<<i) )
+ ones++;
+ }
+ return ones;
+ }
+
+}};
+
+output exec {{
+
+ static int32_t arm_NEG(int32_t val) { return (val >> 31); }
+ static int32_t arm_POS(int32_t val) { return ((~val) >> 31); }
+
+ // Shift Rm by an immediate value
+ inline int32_t
+ shift_rm_imm(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval)
+ {
+ enum ArmShiftType shiftType;
+ shiftType = (enum ArmShiftType) type;
+
+ switch (shiftType)
+ {
+ case LSL:
+ return (base << shamt);
+ case LSR:
+ if (shamt == 0)
+ return (0);
+ else
+ return (base >> shamt);
+ case ASR:
+ if (shamt == 0)
+ return ((uint32_t) ((int32_t) base >> 31L));
+ else
+ return ((uint32_t) (((int32_t) base) >> shamt));
+ case ROR:
+ //shamt = shamt & 0x1f;
+ if (shamt == 0)
+ return (cfval << 31) | (base >> 1); // RRX
+ else
+ return (base << (32 - shamt)) | (base >> shamt);
+ default:
+ fprintf(stderr, "Unhandled shift type\n");
+ exit(1);
+ break;
+ }
+ return 0;
+ }
+
+ // Shift Rm by Rs
+ inline int32_t
+ shift_rm_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval)
+ {
+ enum ArmShiftType shiftType;
+ shiftType = (enum ArmShiftType) type;
+
+ switch (shiftType)
+ {
+ case LSL:
+ if (shamt == 0)
+ return (base);
+ else if (shamt >= 32)
+ return (0);
+ else
+ return (base << shamt);
+ case LSR:
+ if (shamt == 0)
+ return (base);
+ else if (shamt >= 32)
+ return (0);
+ else
+ return (base >> shamt);
+ case ASR:
+ if (shamt == 0)
+ return base;
+ else if (shamt >= 32)
+ return ((uint32_t) ((int32_t) base >> 31L));
+ else
+ return ((uint32_t) (((int32_t) base) >> (int) shamt));
+ case ROR:
+ shamt = shamt & 0x1f;
+ if (shamt == 0)
+ return (base);
+ else
+ return ((base << (32 - shamt)) | (base >> shamt));
+ default:
+ fprintf(stderr, "Unhandled shift type\n");
+ exit(1);
+ break;
+ }
+ return 0;
+ }
+
+
+ // Generate C for a shift by immediate
+ inline int32_t
+ shift_carry_imm(uint32_t base, uint32_t shamt, uint32_t type,
+ uint32_t cfval)
+ {
+ enum ArmShiftType shiftType;
+ shiftType = (enum ArmShiftType) type;
+
+ switch (shiftType)
+ {
+ case LSL:
+ return (base >> (32 - shamt)) & 1;
+ case LSR:
+ if (shamt == 0)
+ return (base >> 31) & 1;
+ else
+ return (base >> (shamt - 1)) & 1;
+ case ASR:
+ if (shamt == 0)
+ return (base >> 31L);
+ else
+ return ((uint32_t) (((int32_t) base) >> (shamt - 1))) & 1;
+ case ROR:
+ shamt = shamt & 0x1f;
+ if (shamt == 0)
+ return (base & 1); // RRX
+ else
+ return (base >> (shamt - 1)) & 1;
+ default:
+ fprintf(stderr, "Unhandled shift type\n");
+ exit(1);
+ break;
+
+ }
+ return 0;
+ }
+
+
+ // Generate C for a shift by Rs
+ inline int32_t
+ shift_carry_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval)
+ {
+ enum ArmShiftType shiftType;
+ shiftType = (enum ArmShiftType) type;
+
+ switch (shiftType)
+ {
+ case LSL:
+ if (shamt == 0)
+ return (!!cfval);
+ else if (shamt == 32)
+ return (base & 1);
+ else if (shamt > 32)
+ return (0);
+ else
+ return ((base >> (32 - shamt)) & 1);
+ case LSR:
+ if (shamt == 0)
+ return (!!cfval);
+ else if (shamt == 32)
+ return (base >> 31);
+ else if (shamt > 32)
+ return (0);
+ else
+ return ((base >> (shamt - 1)) & 1);
+ case ASR:
+ if (shamt == 0)
+ return (!!cfval);
+ else if (shamt >= 32)
+ return (base >> 31L);
+ else
+ return (((uint32_t) (((int32_t) base) >> (shamt - 1))) & 1);
+ case ROR:
+ if (shamt == 0)
+ return (!!cfval);
+ shamt = shamt & 0x1f;
+ if (shamt == 0)
+ return (base >> 31); // RRX
+ else
+ return ((base >> (shamt - 1)) & 1);
+ default:
+ fprintf(stderr, "Unhandled shift type\n");
+ exit(1);
+ break;
+
+ }
+ return 0;
+ }
+
+
+ // Generate the appropriate carry bit for an addition operation
+ inline int32_t
+ arm_add_carry(int32_t result, int32_t lhs, int32_t rhs)
+ {
+ if ((lhs | rhs) >> 30)
+ return ((arm_NEG(lhs) && arm_NEG(rhs)) ||
+ (arm_NEG(lhs) && arm_POS(result)) ||
+ (arm_NEG(rhs) && arm_POS(result)));
+ else
+ return 0;
+ }
+
+ // Generate the appropriate carry bit for a subtraction operation
+ inline int32_t
+ arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs)
+ {
+ if ((lhs >= rhs) || ((rhs | lhs) >> 31))
+ return ((arm_NEG(lhs) && arm_POS(rhs)) ||
+ (arm_NEG(lhs) && arm_POS(result)) ||
+ (arm_POS(rhs) && arm_POS(result)));
+ else
+ return 0;
+ }
+
+ inline int32_t
+ arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs)
+ {
+ if ((lhs | rhs) >> 30)
+ return ((arm_NEG(lhs) && arm_NEG(rhs) && arm_POS(result)) ||
+ (arm_POS(lhs) && arm_POS(rhs) && arm_NEG(result)));
+ else
+ return 0;
+ }
+
+ inline int32_t
+ arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs)
+ {
+ if ((lhs >= rhs) || ((rhs | lhs) >> 31))
+ return ((arm_NEG(lhs) && arm_POS(rhs) && arm_POS(result)) ||
+ (arm_POS(lhs) && arm_NEG(rhs) && arm_NEG(result)));
+ else
+ return 0;
+ }
+
+}};
+