macromem.isa revision 6309
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    microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
76                                   'MicroMemOp',
77                                   {'memacc_code': 'Mem = Ra;',
78                                    'ea_code': 'EA = Rb + (UP ? imm : -imm);',
79                                    'predicate_test': predicateTest},
80                                   ['IsMicroop'])
81
82    header_output = MicroMemDeclare.subst(microLdrUopIop) + \
83                    MicroMemDeclare.subst(microStrUopIop)
84    decoder_output = MicroConstructor.subst(microLdrUopIop) + \
85                     MicroConstructor.subst(microStrUopIop)
86    exec_output = LoadExecute.subst(microLdrUopIop) + \
87                  StoreExecute.subst(microStrUopIop) + \
88                  LoadInitiateAcc.subst(microLdrUopIop) + \
89                  StoreInitiateAcc.subst(microStrUopIop) + \
90                  LoadCompleteAcc.subst(microLdrUopIop) + \
91                  StoreCompleteAcc.subst(microStrUopIop)
92}};
93
94////////////////////////////////////////////////////////////////////
95//
96// Integer = Integer op Immediate microops
97//
98
99def template MicroIntDeclare {{
100    class %(class_name)s : public %(base_class)s
101    {
102      public:
103        %(class_name)s(ExtMachInst machInst,
104                       RegIndex _ura, RegIndex _urb,
105                       uint8_t _imm);
106        %(BasicExecDeclare)s
107    };
108}};
109
110let {{
111    microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
112                                    'MicroIntOp',
113                                    {'code': 'Ra = Rb + imm;',
114                                     'predicate_test': predicateTest},
115                                    ['IsMicroop'])
116
117    microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
118                                    'MicroIntOp',
119                                    {'code': 'Ra = Rb - imm;',
120                                     'predicate_test': predicateTest},
121                                    ['IsMicroop'])
122
123    header_output = MicroIntDeclare.subst(microAddiUopIop) + \
124                    MicroIntDeclare.subst(microSubiUopIop)
125    decoder_output = MicroConstructor.subst(microAddiUopIop) + \
126                     MicroConstructor.subst(microSubiUopIop)
127    exec_output = PredOpExecute.subst(microAddiUopIop) + \
128                  PredOpExecute.subst(microSubiUopIop)
129}};
130
131////////////////////////////////////////////////////////////////////
132//
133// Macro Memory-format instructions
134//
135
136def template MacroStoreDeclare {{
137/**
138 * Static instructions class for a store multiple instruction
139 */
140class %(class_name)s : public %(base_class)s
141{
142    public:
143        // Constructor
144        %(class_name)s(ExtMachInst machInst);
145        %(BasicExecDeclare)s
146};
147}};
148
149def template MacroStoreConstructor {{
150inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
151    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
152{
153    %(constructor)s;
154    uint32_t regs_to_handle = reglist;
155    uint32_t start_addr = 0;
156
157    switch (puswl)
158    {
159        case 0x00: //       stmda
160        case 0x01: //     L ldmda_l
161        case 0x02: //    W  stmda_w
162        case 0x03: //    WL ldmda_wl
163            start_addr = (ones << 2) - 4;
164            break;
165        case 0x08: //  U    stmia_u
166        case 0x09: //  U  L ldmia_ul
167        case 0x0a: //  U W  stmia
168        case 0x0b: //  U WL ldmia
169            start_addr = 0;
170            break;
171        case 0x10: // P     stmdb
172        case 0x11: // P   L ldmdb
173        case 0x12: // P  W  stmdb
174        case 0x13: // P  WL ldmdb
175            start_addr = (ones << 2); // U-bit is already 0 for subtract
176            break;
177        case 0x18: // PU    stmib
178        case 0x19: // PU  L ldmib
179        case 0x1a: // PU W  stmib
180        case 0x1b: // PU WL ldmib
181            start_addr = 4;
182            break;
183        default:
184            panic("Unhandled Load/Store Multiple Instruction, "
185                "puswl = 0x%x", (unsigned) puswl);
186            break;
187    }
188
189    // Add 0 to Rn and stick it in Raddr (register 17).
190    // This is equivalent to a move.
191    microOps[0] = new MicroAddiUop(machInst, 17, RN, 0);
192
193    unsigned j = 0;
194    for (int i = 1; i < ones+1; i++) {
195        // Get next available bit for transfer
196        while (! ( regs_to_handle & (1<<j)))
197            j++;
198        regs_to_handle &= ~(1<<j);
199
200        if (loadop)
201            microOps[i] = new MicroLdrUop(machInst, j, 17, start_addr);
202        else
203            microOps[i] = new MicroStrUop(machInst, j, 17, start_addr);
204
205        if (up)
206            start_addr += 4;
207        else
208            start_addr -= 4;
209    }
210
211    if (writeback) {
212        if (up) {
213            microOps[numMicroops-1] =
214                new MicroAddiUop(machInst, RN, RN, ones * 4);
215        } else {
216            microOps[numMicroops-1] =
217                new MicroSubiUop(machInst, RN, RN, ones * 4);
218        }
219    }
220    microOps[numMicroops-1]->setLastMicroop();
221}
222
223}};
224
225def template MacroStoreExecute {{
226Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
227{
228    Fault fault = NoFault;
229
230    %(fp_enable_check)s;
231    %(op_decl)s;
232    %(op_rd)s;
233    %(code)s;
234    if (fault == NoFault)
235    {
236        %(op_wb)s;
237    }
238
239    return fault;
240}
241}};
242
243def template MacroFPAConstructor {{
244inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
245    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
246{
247    %(constructor)s;
248
249    uint32_t start_addr = 0;
250
251    if (prepost)
252        start_addr = disp8;
253    else
254        start_addr = 0;
255
256    emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr);
257
258    if (writeback)
259    {
260        if (up) {
261            microOps[numMicroops-1] =
262                new MicroAddiUop(machInst, RN, RN, disp8);
263        } else {
264            microOps[numMicroops-1] =
265                new MicroSubiUop(machInst, RN, RN, disp8);
266        }
267    }
268    microOps[numMicroops-1]->setLastMicroop();
269}
270
271}};
272
273
274def template MacroFMConstructor {{
275inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
276    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
277{
278    %(constructor)s;
279
280    uint32_t start_addr = 0;
281
282    if (prepost)
283        start_addr = disp8;
284    else
285        start_addr = 0;
286
287    for (int i = 0; i < count; i++)
288        emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr);
289
290    if (writeback) {
291        if (up) {
292            microOps[numMicroops-1] =
293                new MicroAddiUop(machInst, RN, RN, disp8);
294        } else {
295            microOps[numMicroops-1] =
296                new MicroSubiUop(machInst, RN, RN, disp8);
297        }
298    }
299    microOps[numMicroops-1]->setLastMicroop();
300}
301}};
302
303
304def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
305    iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
306    header_output = MacroStoreDeclare.subst(iop)
307    decoder_output = MacroStoreConstructor.subst(iop)
308    decode_block = BasicDecode.subst(iop)
309    exec_output = MacroStoreExecute.subst(iop)
310}};
311
312def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
313    iop = InstObjParams(name, Name, 'ArmMacroFPAOp',
314                        {"code": code,
315                         "predicate_test": predicateTest},
316                        opt_flags)
317    header_output = BasicDeclare.subst(iop)
318    decoder_output = MacroFPAConstructor.subst(iop)
319    decode_block = BasicDecode.subst(iop)
320    exec_output = PredOpExecute.subst(iop)
321}};
322
323def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
324    iop = InstObjParams(name, Name, 'ArmMacroFMOp',
325                        {"code": code,
326                         "predicate_test": predicateTest},
327                        opt_flags)
328    header_output = BasicDeclare.subst(iop)
329    decoder_output = MacroFMConstructor.subst(iop)
330    decode_block = BasicDecode.subst(iop)
331    exec_output = PredOpExecute.subst(iop)
332}};
333