summaryrefslogtreecommitdiff
path: root/src/arch/arm/isa/formats/macromem.isa
diff options
context:
space:
mode:
authorStephen Hines <hines@cs.fsu.edu>2009-04-05 18:53:15 -0700
committerStephen Hines <hines@cs.fsu.edu>2009-04-05 18:53:15 -0700
commit7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (patch)
tree727269d84fb4ba0e7db6e1c7ffdeb3e114b71773 /src/arch/arm/isa/formats/macromem.isa
parent65332ef3a9df48f7ff11b417b0ffc4a171824931 (diff)
downloadgem5-7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9.tar.xz
arm: add ARM support to M5
Diffstat (limited to 'src/arch/arm/isa/formats/macromem.isa')
-rw-r--r--src/arch/arm/isa/formats/macromem.isa389
1 files changed, 389 insertions, 0 deletions
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)
+}};
+
+
+