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