macromem.isa revision 7130:12d7f945261f
1// -*- mode:c++ -*-
2
3// Copyright (c) 2007-2008 The Florida State University
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Stephen Hines
30//          Gabe Black
31
32////////////////////////////////////////////////////////////////////
33//
34// Common microop templates
35//
36
37def template MicroConstructor {{
38    inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
39                                          RegIndex _ura,
40                                          RegIndex _urb,
41                                          uint8_t _imm)
42        : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
43                         _ura, _urb, _imm)
44    {
45        %(constructor)s;
46    }
47}};
48
49////////////////////////////////////////////////////////////////////
50//
51// Load/store microops
52//
53
54def template MicroMemDeclare {{
55    class %(class_name)s : public %(base_class)s
56    {
57      public:
58        %(class_name)s(ExtMachInst machInst,
59                       RegIndex _ura, RegIndex _urb,
60                       uint8_t _imm);
61        %(BasicExecDeclare)s
62        %(InitiateAccDeclare)s
63        %(CompleteAccDeclare)s
64    };
65}};
66
67let {{
68    microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
69                                   'MicroMemOp',
70                                   {'memacc_code': 'Ra = Mem;',
71                                    'ea_code': 'EA = Rb + (UP ? imm : -imm);',
72                                    'predicate_test': predicateTest},
73                                   ['IsMicroop'])
74
75    microLdrRetUopCode = '''
76        Ra = Mem;
77        Cpsr = cpsrWriteByInstr(Cpsr, Spsr, 0xF, true);
78    '''
79    microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
80                                      'MicroMemOp',
81                                      {'memacc_code': microLdrRetUopCode,
82                                       'ea_code':
83                                          'EA = Rb + (UP ? imm : -imm);',
84                                       'predicate_test': predicateTest},
85                                      ['IsMicroop'])
86
87    microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
88                                   'MicroMemOp',
89                                   {'memacc_code': 'Mem = Ra;',
90                                    'ea_code': 'EA = Rb + (UP ? imm : -imm);',
91                                    'predicate_test': predicateTest},
92                                   ['IsMicroop'])
93
94    header_output = MicroMemDeclare.subst(microLdrUopIop) + \
95                    MicroMemDeclare.subst(microLdrRetUopIop) + \
96                    MicroMemDeclare.subst(microStrUopIop)
97    decoder_output = MicroConstructor.subst(microLdrUopIop) + \
98                     MicroConstructor.subst(microLdrRetUopIop) + \
99                     MicroConstructor.subst(microStrUopIop)
100    exec_output = LoadExecute.subst(microLdrUopIop) + \
101                  LoadExecute.subst(microLdrRetUopIop) + \
102                  StoreExecute.subst(microStrUopIop) + \
103                  LoadInitiateAcc.subst(microLdrUopIop) + \
104                  LoadInitiateAcc.subst(microLdrRetUopIop) + \
105                  StoreInitiateAcc.subst(microStrUopIop) + \
106                  LoadCompleteAcc.subst(microLdrUopIop) + \
107                  LoadCompleteAcc.subst(microLdrRetUopIop) + \
108                  StoreCompleteAcc.subst(microStrUopIop)
109}};
110
111////////////////////////////////////////////////////////////////////
112//
113// Integer = Integer op Immediate microops
114//
115
116def template MicroIntDeclare {{
117    class %(class_name)s : public %(base_class)s
118    {
119      public:
120        %(class_name)s(ExtMachInst machInst,
121                       RegIndex _ura, RegIndex _urb,
122                       uint8_t _imm);
123        %(BasicExecDeclare)s
124    };
125}};
126
127let {{
128    microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
129                                    'MicroIntOp',
130                                    {'code': 'Ra = Rb + imm;',
131                                     'predicate_test': predicateTest},
132                                    ['IsMicroop'])
133
134    microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
135                                    'MicroIntOp',
136                                    {'code': 'Ra = Rb - imm;',
137                                     'predicate_test': predicateTest},
138                                    ['IsMicroop'])
139
140    header_output = MicroIntDeclare.subst(microAddiUopIop) + \
141                    MicroIntDeclare.subst(microSubiUopIop)
142    decoder_output = MicroConstructor.subst(microAddiUopIop) + \
143                     MicroConstructor.subst(microSubiUopIop)
144    exec_output = PredOpExecute.subst(microAddiUopIop) + \
145                  PredOpExecute.subst(microSubiUopIop)
146}};
147
148////////////////////////////////////////////////////////////////////
149//
150// Macro Memory-format instructions
151//
152
153def template MacroStoreDeclare {{
154/**
155 * Static instructions class for a store multiple instruction
156 */
157class %(class_name)s : public %(base_class)s
158{
159    public:
160        // Constructor
161        %(class_name)s(ExtMachInst machInst);
162        %(BasicExecDeclare)s
163};
164}};
165
166def template MacroStoreConstructor {{
167inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
168    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
169{
170    %(constructor)s;
171    uint32_t regs = reglist;
172    uint32_t addr = 0;
173    bool up = machInst.puswl.up;
174
175    if (!up)
176        addr = (ones << 2) - 4;
177
178    if (machInst.puswl.prepost)
179        addr += 4;
180
181    // Add 0 to Rn and stick it in ureg0.
182    // This is equivalent to a move.
183    microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0);
184
185    unsigned reg = 0;
186    bool force_user = machInst.puswl.psruser & !OPCODE_15;
187    bool exception_ret = machInst.puswl.psruser & OPCODE_15;
188
189    for (int i = 1; i < ones + 1; i++) {
190        // Find the next register.
191        while (!bits(regs, reg))
192            reg++;
193        replaceBits(regs, reg, 0);
194
195        unsigned regIdx = reg;
196        if (force_user) {
197            regIdx = intRegForceUser(regIdx);
198        }
199
200        if (machInst.puswl.loadOp) {
201            if (reg == INTREG_PC && exception_ret) {
202                // This must be the exception return form of ldm.
203                microOps[i] =
204                    new MicroLdrRetUop(machInst, regIdx, INTREG_UREG0, addr);
205            } else {
206                microOps[i] =
207                    new MicroLdrUop(machInst, regIdx, INTREG_UREG0, addr);
208            }
209        } else {
210            microOps[i] =
211                new MicroStrUop(machInst, regIdx, INTREG_UREG0, addr);
212        }
213
214        if (up)
215            addr += 4;
216        else
217            addr -= 4;
218    }
219
220    StaticInstPtr &lastUop = microOps[numMicroops - 1];
221    if (machInst.puswl.writeback) {
222        if (up) {
223            lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
224        } else {
225            lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
226        }
227    }
228    lastUop->setLastMicroop();
229}
230
231}};
232
233def template MacroStoreExecute {{
234Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
235{
236    Fault fault = NoFault;
237
238    %(fp_enable_check)s;
239    %(op_decl)s;
240    %(op_rd)s;
241    %(code)s;
242    if (fault == NoFault)
243    {
244        %(op_wb)s;
245    }
246
247    return fault;
248}
249}};
250
251def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
252    iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
253    header_output = MacroStoreDeclare.subst(iop)
254    decoder_output = MacroStoreConstructor.subst(iop)
255    decode_block = BasicDecode.subst(iop)
256    exec_output = MacroStoreExecute.subst(iop)
257}};
258