ARM: Make the exception return form of ldm restore CPSR.
[gem5.git] / src / arch / arm / isa / formats / macromem.isa
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
37 def 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
54 def 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
67 let {{
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
116 def 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
127 let {{
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
153 let {{
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
180 def template MacroStoreDeclare {{
181 /**
182 * Static instructions class for a store multiple instruction
183 */
184 class %(class_name)s : public %(base_class)s
185 {
186 public:
187 // Constructor
188 %(class_name)s(ExtMachInst machInst);
189 %(BasicExecDeclare)s
190 };
191 }};
192
193 def template MacroStoreConstructor {{
194 inline %(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
258 def template MacroStoreExecute {{
259 Fault %(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
276 def template MacroFPAConstructor {{
277 inline %(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
307 def template MacroFMConstructor {{
308 inline %(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
337 def 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
345 def 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
356 def 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 }};