macromem.isa revision 6253
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
31////////////////////////////////////////////////////////////////////
32//
33// Macro Memory-format instructions
34//
35
36def template MacroStoreDeclare {{
37/**
38 * Static instructions class for a store multiple instruction
39 */
40class %(class_name)s : public %(base_class)s
41{
42    public:
43        // Constructor
44        %(class_name)s(ExtMachInst machInst);
45        %(BasicExecDeclare)s
46};
47}};
48
49def template MacroStoreConstructor {{
50inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
51    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
52{
53    %(constructor)s;
54    uint32_t regs_to_handle = reglist;
55    uint32_t j = 0,
56             start_addr = 0,
57             end_addr = 0;
58
59    switch (puswl)
60    {
61        case 0x01: //     L ldmda_l
62            start_addr = (ones << 2) - 4;
63            end_addr = 0;
64            break;
65        case 0x03: //    WL ldmda_wl
66            start_addr = (ones << 2) - 4;
67            end_addr = 0;
68            break;
69        case 0x08: //  U    stmia_u
70            start_addr = 0;
71            end_addr = (ones << 2) - 4;
72            break;
73        case 0x09: //  U  L ldmia_ul
74            start_addr = 0;
75            end_addr = (ones << 2) - 4;
76            break;
77        case 0x0b: //  U WL ldmia
78            start_addr = 0;
79            end_addr = (ones << 2) - 4;
80            break;
81        case 0x11: // P   L ldmdb
82            start_addr = (ones << 2); // U-bit is already 0 for subtract
83            end_addr = 4; // negative 4
84            break;
85        case 0x12: // P  W  stmdb
86            start_addr = (ones << 2); // U-bit is already 0 for subtract
87            end_addr = 4; // negative 4
88            break;
89        case 0x18: // PU    stmib
90            start_addr = 4;
91            end_addr = (ones << 2) + 4;
92            break;
93        case 0x19: // PU  L ldmib
94            start_addr = 4;
95            end_addr = (ones << 2) + 4;
96            break;
97        default:
98            panic("Unhandled Load/Store Multiple Instruction");
99            break;
100    }
101
102    //TODO - Add addi_uop/subi_uop here to create starting addresses
103    //Just using addi with 0 offset makes a "copy" of Rn for our use
104    uint32_t newMachInst = 0;
105    newMachInst = machInst & 0xffff0000;
106    microOps[0] = new Addi_uop(newMachInst);
107
108    for (int i = 1; i < ones+1; i++)
109    {
110        // Get next available bit for transfer
111        while (! ( regs_to_handle & (1<<j)))
112            j++;
113        regs_to_handle &= ~(1<<j);
114
115        microOps[i] = gen_ldrstr_uop(machInst, loadop, j, start_addr);
116
117        if (up)
118            start_addr += 4;
119        else
120            start_addr -= 4;
121    }
122
123    /* TODO: Take a look at how these 2 values should meet together
124    if (start_addr != (end_addr - 4))
125    {
126        fprintf(stderr, "start_addr: %d\n", start_addr);
127        fprintf(stderr, "end_addr:   %d\n", end_addr);
128        panic("start_addr does not meet end_addr");
129    }
130    */
131
132    if (writeback)
133    {
134        uint32_t newMachInst = machInst & 0xf0000000;
135        uint32_t rn = (machInst >> 16) & 0x0f;
136        // 3322 2222 2222 1111 1111 11
137        // 1098 7654 3210 9876 5432 1098 7654 3210
138        // COND 0010 0100 [RN] [RD] 0000 [  IMM  ]
139        // sub rn, rn, imm
140        newMachInst |= 0x02400000;
141        newMachInst |= ((rn << 16) | (rn << 12));
142        newMachInst |= (ones << 2);
143        if (up)
144        {
145            microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
146        }
147        else
148        {
149            microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
150        }
151    }
152    microOps[numMicroops-1]->setLastMicroop();
153}
154
155}};
156
157def template MacroStoreExecute {{
158Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
159{
160    Fault fault = NoFault;
161
162    %(fp_enable_check)s;
163    %(op_decl)s;
164    %(op_rd)s;
165    %(code)s;
166    if (fault == NoFault)
167    {
168        %(op_wb)s;
169    }
170
171    return fault;
172}
173}};
174
175def template MacroFPAConstructor {{
176inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
177    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
178{
179    %(constructor)s;
180
181    uint32_t start_addr = 0;
182
183    if (prepost)
184        start_addr = disp8;
185    else
186        start_addr = 0;
187
188    emit_ldfstf_uops(microOps, 0, machInst, loadop, up, start_addr);
189
190    if (writeback)
191    {
192        uint32_t newMachInst = machInst & 0xf0000000;
193        uint32_t rn = (machInst >> 16) & 0x0f;
194        // 3322 2222 2222 1111 1111 11
195        // 1098 7654 3210 9876 5432 1098 7654 3210
196        // COND 0010 0100 [RN] [RD] 0000 [  IMM  ]
197        // sub rn, rn, imm
198        newMachInst |= 0x02400000;
199        newMachInst |= ((rn << 16) | (rn << 12));
200        if (up)
201        {
202            newMachInst |= disp8;
203            microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
204        }
205        else
206        {
207            newMachInst |= disp8;
208            microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
209        }
210    }
211    microOps[numMicroops-1]->setLastMicroop();
212}
213
214}};
215
216
217def template MacroFMConstructor {{
218inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
219    : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
220{
221    %(constructor)s;
222
223    uint32_t start_addr = 0;
224
225    if (prepost)
226        start_addr = disp8;
227    else
228        start_addr = 0;
229
230    for (int i = 0; i < count; i++)
231    {
232        emit_ldfstf_uops(microOps, 3*i, machInst, loadop, up, start_addr);
233    }
234
235    if (writeback)
236    {
237        uint32_t newMachInst = machInst & 0xf0000000;
238        uint32_t rn = (machInst >> 16) & 0x0f;
239        // 3322 2222 2222 1111 1111 11
240        // 1098 7654 3210 9876 5432 1098 7654 3210
241        // COND 0010 0100 [RN] [RD] 0000 [  IMM  ]
242        // sub rn, rn, imm
243        newMachInst |= 0x02400000;
244        newMachInst |= ((rn << 16) | (rn << 12));
245        if (up)
246        {
247            newMachInst |= disp8;
248            microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
249        }
250        else
251        {
252            newMachInst |= disp8;
253            microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
254        }
255    }
256    microOps[numMicroops-1]->setLastMicroop();
257}
258}};
259
260
261def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
262    iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
263    header_output = MacroStoreDeclare.subst(iop)
264    decoder_output = MacroStoreConstructor.subst(iop)
265    decode_block = BasicDecode.subst(iop)
266    exec_output = MacroStoreExecute.subst(iop)
267}};
268
269def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
270    iop = InstObjParams(name, Name, 'ArmMacroFPAOp',
271                        {"code": code,
272                         "predicate_test": predicateTest},
273                        opt_flags)
274    header_output = BasicDeclare.subst(iop)
275    decoder_output = MacroFPAConstructor.subst(iop)
276    decode_block = BasicDecode.subst(iop)
277    exec_output = PredOpExecute.subst(iop)
278}};
279
280def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
281    iop = InstObjParams(name, Name, 'ArmMacroFMOp',
282                        {"code": code,
283                         "predicate_test": predicateTest},
284                        opt_flags)
285    header_output = BasicDeclare.subst(iop)
286    decoder_output = MacroFMConstructor.subst(iop)
287    decode_block = BasicDecode.subst(iop)
288    exec_output = PredOpExecute.subst(iop)
289}};
290