macromem.isa revision 6755
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    bool forceUser = machInst.puswl.psruser;
214    for (int i = 1; i < ones + 1; i++) {
215        // Find the next register.
216        while (!bits(regs, reg))
217            reg++;
218        replaceBits(regs, reg, 0);
219
220        unsigned regIdx = reg;
221        if (forceUser) {
222            regIdx = intRegForceUser(regIdx);
223        }
224
225        if (machInst.puswl.loadOp) {
226            if (reg == INTREG_PC && forceUser) {
227                // This must be the exception return form of ldm.
228                microOps[i] =
229                    new MicroLdrRetUop(machInst, regIdx, INTREG_UREG0, addr);
230            } else {
231                microOps[i] =
232                    new MicroLdrUop(machInst, regIdx, INTREG_UREG0, addr);
233            }
234        } else {
235            microOps[i] =
236                new MicroStrUop(machInst, regIdx, INTREG_UREG0, addr);
237        }
238
239        if (up)
240            addr += 4;
241        else
242            addr -= 4;
243    }
244
245    StaticInstPtr &lastUop = microOps[numMicroops - 1];
246    if (machInst.puswl.writeback) {
247        if (up) {
248            lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
249        } else {
250            lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
251        }
252    }
253    lastUop->setLastMicroop();
254}
255
256}};
257
258def template MacroStoreExecute {{
259Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
260{
261    Fault fault = NoFault;
262
263    %(fp_enable_check)s;
264    %(op_decl)s;
265    %(op_rd)s;
266    %(code)s;
267    if (fault == NoFault)
268    {
269        %(op_wb)s;
270    }
271
272    return fault;
273}
274}};
275
276def template MacroFPAConstructor {{
277inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
278    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
279{
280    %(constructor)s;
281
282    uint32_t start_addr = 0;
283
284    if (prepost)
285        start_addr = disp8;
286    else
287        start_addr = 0;
288
289    emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr);
290
291    if (writeback)
292    {
293        if (up) {
294            microOps[numMicroops - 1] =
295                new MicroAddiUop(machInst, RN, RN, disp8);
296        } else {
297            microOps[numMicroops - 1] =
298                new MicroSubiUop(machInst, RN, RN, disp8);
299        }
300    }
301    microOps[numMicroops - 1]->setLastMicroop();
302}
303
304}};
305
306
307def template MacroFMConstructor {{
308inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
309    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
310{
311    %(constructor)s;
312
313    uint32_t start_addr = 0;
314
315    if (prepost)
316        start_addr = disp8;
317    else
318        start_addr = 0;
319
320    for (int i = 0; i < count; i++)
321        emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr);
322
323    if (writeback) {
324        if (up) {
325            microOps[numMicroops - 1] =
326                new MicroAddiUop(machInst, RN, RN, disp8);
327        } else {
328            microOps[numMicroops - 1] =
329                new MicroSubiUop(machInst, RN, RN, disp8);
330        }
331    }
332    microOps[numMicroops - 1]->setLastMicroop();
333}
334}};
335
336
337def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
338    iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
339    header_output = MacroStoreDeclare.subst(iop)
340    decoder_output = MacroStoreConstructor.subst(iop)
341    decode_block = BasicDecode.subst(iop)
342    exec_output = MacroStoreExecute.subst(iop)
343}};
344
345def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
346    iop = InstObjParams(name, Name, 'ArmMacroFPAOp',
347                        {"code": code,
348                         "predicate_test": predicateTest},
349                        opt_flags)
350    header_output = BasicDeclare.subst(iop)
351    decoder_output = MacroFPAConstructor.subst(iop)
352    decode_block = BasicDecode.subst(iop)
353    exec_output = PredOpExecute.subst(iop)
354}};
355
356def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
357    iop = InstObjParams(name, Name, 'ArmMacroFMOp',
358                        {"code": code,
359                         "predicate_test": predicateTest},
360                        opt_flags)
361    header_output = BasicDeclare.subst(iop)
362    decoder_output = MacroFMConstructor.subst(iop)
363    decode_block = BasicDecode.subst(iop)
364    exec_output = PredOpExecute.subst(iop)
365}};
366