macromem.isa revision 6754
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// Moving to/from double floating point registers
151//
152
153let {{
154    microMvtdUopIop = InstObjParams('mvtd_uop', 'MicroMvtdUop',
155                                    'PredOp',
156                                    {'code': 'Fd.ud = (Rhi.ud << 32) | Rlo;',
157                                     'predicate_test': predicateTest},
158                                    ['IsMicroop'])
159
160    microMvfdUopIop = InstObjParams('mvfd_uop', 'MicroMvfdUop',
161                                    'PredOp',
162                                    {'code': '''Rhi = bits(Fd.ud, 63, 32);
163                                                Rlo = bits(Fd.ud, 31, 0);''',
164                                     'predicate_test': predicateTest},
165                                    ['IsMicroop'])
166
167    header_output = BasicDeclare.subst(microMvtdUopIop) + \
168                    BasicDeclare.subst(microMvfdUopIop)
169    decoder_output = BasicConstructor.subst(microMvtdUopIop) + \
170                     BasicConstructor.subst(microMvfdUopIop)
171    exec_output = PredOpExecute.subst(microMvtdUopIop) + \
172                  PredOpExecute.subst(microMvfdUopIop)
173}};
174
175////////////////////////////////////////////////////////////////////
176//
177// Macro Memory-format instructions
178//
179
180def template MacroStoreDeclare {{
181/**
182 * Static instructions class for a store multiple instruction
183 */
184class %(class_name)s : public %(base_class)s
185{
186    public:
187        // Constructor
188        %(class_name)s(ExtMachInst machInst);
189        %(BasicExecDeclare)s
190};
191}};
192
193def template MacroStoreConstructor {{
194inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
195    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
196{
197    %(constructor)s;
198    uint32_t regs = reglist;
199    uint32_t addr = 0;
200    bool up = machInst.puswl.up;
201
202    if (!up)
203        addr = (ones << 2) - 4;
204
205    if (machInst.puswl.prepost)
206        addr += 4;
207
208    // Add 0 to Rn and stick it in ureg0.
209    // This is equivalent to a move.
210    microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0);
211
212    unsigned reg = 0;
213    for (int i = 1; i < ones + 1; i++) {
214        // Find the next register.
215        while (!bits(regs, reg))
216            reg++;
217        replaceBits(regs, reg, 0);
218
219        unsigned regIdx = reg;
220        if (machInst.puswl.psruser) {
221            regIdx = intRegForceUser(regIdx);
222        }
223
224        if (machInst.puswl.loadOp) {
225            microOps[i] =
226                new MicroLdrUop(machInst, regIdx, INTREG_UREG0, addr);
227        } else {
228            microOps[i] =
229                new MicroStrUop(machInst, regIdx, INTREG_UREG0, addr);
230        }
231
232        if (up)
233            addr += 4;
234        else
235            addr -= 4;
236    }
237
238    StaticInstPtr &lastUop = microOps[numMicroops - 1];
239    if (machInst.puswl.writeback) {
240        if (up) {
241            lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
242        } else {
243            lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
244        }
245    }
246    lastUop->setLastMicroop();
247}
248
249}};
250
251def template MacroStoreExecute {{
252Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
253{
254    Fault fault = NoFault;
255
256    %(fp_enable_check)s;
257    %(op_decl)s;
258    %(op_rd)s;
259    %(code)s;
260    if (fault == NoFault)
261    {
262        %(op_wb)s;
263    }
264
265    return fault;
266}
267}};
268
269def template MacroFPAConstructor {{
270inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
271    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
272{
273    %(constructor)s;
274
275    uint32_t start_addr = 0;
276
277    if (prepost)
278        start_addr = disp8;
279    else
280        start_addr = 0;
281
282    emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr);
283
284    if (writeback)
285    {
286        if (up) {
287            microOps[numMicroops - 1] =
288                new MicroAddiUop(machInst, RN, RN, disp8);
289        } else {
290            microOps[numMicroops - 1] =
291                new MicroSubiUop(machInst, RN, RN, disp8);
292        }
293    }
294    microOps[numMicroops - 1]->setLastMicroop();
295}
296
297}};
298
299
300def template MacroFMConstructor {{
301inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
302    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
303{
304    %(constructor)s;
305
306    uint32_t start_addr = 0;
307
308    if (prepost)
309        start_addr = disp8;
310    else
311        start_addr = 0;
312
313    for (int i = 0; i < count; i++)
314        emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr);
315
316    if (writeback) {
317        if (up) {
318            microOps[numMicroops - 1] =
319                new MicroAddiUop(machInst, RN, RN, disp8);
320        } else {
321            microOps[numMicroops - 1] =
322                new MicroSubiUop(machInst, RN, RN, disp8);
323        }
324    }
325    microOps[numMicroops - 1]->setLastMicroop();
326}
327}};
328
329
330def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
331    iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
332    header_output = MacroStoreDeclare.subst(iop)
333    decoder_output = MacroStoreConstructor.subst(iop)
334    decode_block = BasicDecode.subst(iop)
335    exec_output = MacroStoreExecute.subst(iop)
336}};
337
338def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
339    iop = InstObjParams(name, Name, 'ArmMacroFPAOp',
340                        {"code": code,
341                         "predicate_test": predicateTest},
342                        opt_flags)
343    header_output = BasicDeclare.subst(iop)
344    decoder_output = MacroFPAConstructor.subst(iop)
345    decode_block = BasicDecode.subst(iop)
346    exec_output = PredOpExecute.subst(iop)
347}};
348
349def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
350    iop = InstObjParams(name, Name, 'ArmMacroFMOp',
351                        {"code": code,
352                         "predicate_test": predicateTest},
353                        opt_flags)
354    header_output = BasicDeclare.subst(iop)
355    decoder_output = MacroFMConstructor.subst(iop)
356    decode_block = BasicDecode.subst(iop)
357    exec_output = PredOpExecute.subst(iop)
358}};
359