6f507b9b1991d77360a5f2b8786fa064e8789681
[gem5.git] / src / arch / arm / isa / insts / macromem.isa
1 // -*- mode:c++ -*-
2
3 // Copyright (c) 2010-2014 ARM Limited
4 // All rights reserved
5 //
6 // The license below extends only to copyright in the software and shall
7 // not be construed as granting a license to any other intellectual
8 // property including but not limited to intellectual property relating
9 // to a hardware implementation of the functionality of the software
10 // licensed hereunder. You may use the software subject to the license
11 // terms below provided that you ensure that this notice is replicated
12 // unmodified and in its entirety in all distributions of the software,
13 // modified or unmodified, in source code or in binary form.
14 //
15 // Copyright (c) 2007-2008 The Florida State University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met: redistributions of source code must retain the above copyright
21 // notice, this list of conditions and the following disclaimer;
22 // redistributions in binary form must reproduce the above copyright
23 // notice, this list of conditions and the following disclaimer in the
24 // documentation and/or other materials provided with the distribution;
25 // neither the name of the copyright holders nor the names of its
26 // contributors may be used to endorse or promote products derived from
27 // this software without specific prior written permission.
28 //
29 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
41 ////////////////////////////////////////////////////////////////////
42 //
43 // Load/store microops
44 //
45
46 let {{
47 microLdrUopCode = "IWRa = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
48 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
49 'MicroMemOp',
50 {'memacc_code': microLdrUopCode,
51 'ea_code': 'EA = URb + (up ? imm : -imm);',
52 'predicate_test': predicateTest},
53 ['IsMicroop'])
54
55 microLdr2UopCode = '''
56 uint64_t data = Mem_ud;
57 Dest = cSwap((uint32_t) data, ((CPSR)Cpsr).e);
58 IWDest2 = cSwap((uint32_t) (data >> 32),
59 ((CPSR)Cpsr).e);
60 '''
61 microLdr2UopIop = InstObjParams('ldr2_uop', 'MicroLdr2Uop',
62 'MicroMemPairOp',
63 {'memacc_code': microLdr2UopCode,
64 'ea_code': 'EA = URb + (up ? imm : -imm);',
65 'predicate_test': predicateTest},
66 ['IsMicroop'])
67
68 microLdrFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
69 microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop',
70 'MicroMemOp',
71 {'memacc_code': microLdrFpUopCode,
72 'ea_code': vfpEnabledCheckCode +
73 'EA = URb + (up ? imm : -imm);',
74 'predicate_test': predicateTest},
75 ['IsMicroop'])
76
77 microLdrDBFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
78 microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop',
79 'MicroMemOp',
80 {'memacc_code': microLdrFpUopCode,
81 'ea_code': vfpEnabledCheckCode + '''
82 EA = URb + (up ? imm : -imm) +
83 (((CPSR)Cpsr).e ? 4 : 0);
84 ''',
85 'predicate_test': predicateTest},
86 ['IsMicroop'])
87
88 microLdrDTFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
89 microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop',
90 'MicroMemOp',
91 {'memacc_code': microLdrFpUopCode,
92 'ea_code': vfpEnabledCheckCode + '''
93 EA = URb + (up ? imm : -imm) -
94 (((CPSR)Cpsr).e ? 4 : 0);
95 ''',
96 'predicate_test': predicateTest},
97 ['IsMicroop'])
98
99 microRetUopCode = '''
100 CPSR old_cpsr = Cpsr;
101 SCTLR sctlr = Sctlr;
102
103 CPSR new_cpsr =
104 cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF, true,
105 sctlr.nmfi, xc->tcBase());
106 Cpsr = ~CondCodesMask & new_cpsr;
107 CondCodesNZ = new_cpsr.nz;
108 CondCodesC = new_cpsr.c;
109 CondCodesV = new_cpsr.v;
110 CondCodesGE = new_cpsr.ge;
111 IWNPC = cSwap(%s, old_cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
112 NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
113 | (((CPSR)Spsr).it1 & 0x3);
114 SevMailbox = 1;
115 '''
116
117 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
118 'MicroMemOp',
119 {'memacc_code':
120 microRetUopCode % 'Mem_uw',
121 'ea_code':
122 'EA = URb + (up ? imm : -imm);',
123 'predicate_test': condPredicateTest},
124 ['IsMicroop','IsNonSpeculative',
125 'IsSerializeAfter', 'IsSquashAfter'])
126
127 microStrUopCode = "Mem = cSwap(URa_uw, ((CPSR)Cpsr).e);"
128 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
129 'MicroMemOp',
130 {'memacc_code': microStrUopCode,
131 'postacc_code': "",
132 'ea_code': 'EA = URb + (up ? imm : -imm);',
133 'predicate_test': predicateTest},
134 ['IsMicroop'])
135
136 microStrFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
137 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
138 'MicroMemOp',
139 {'memacc_code': microStrFpUopCode,
140 'postacc_code': "",
141 'ea_code': vfpEnabledCheckCode +
142 'EA = URb + (up ? imm : -imm);',
143 'predicate_test': predicateTest},
144 ['IsMicroop'])
145
146 microStrDBFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
147 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop',
148 'MicroMemOp',
149 {'memacc_code': microStrFpUopCode,
150 'postacc_code': "",
151 'ea_code': vfpEnabledCheckCode + '''
152 EA = URb + (up ? imm : -imm) +
153 (((CPSR)Cpsr).e ? 4 : 0);
154 ''',
155 'predicate_test': predicateTest},
156 ['IsMicroop'])
157
158 microStrDTFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
159 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop',
160 'MicroMemOp',
161 {'memacc_code': microStrFpUopCode,
162 'postacc_code': "",
163 'ea_code': vfpEnabledCheckCode + '''
164 EA = URb + (up ? imm : -imm) -
165 (((CPSR)Cpsr).e ? 4 : 0);
166 ''',
167 'predicate_test': predicateTest},
168 ['IsMicroop'])
169
170 header_output = decoder_output = exec_output = ''
171
172 loadIops = (microLdrUopIop, microLdrRetUopIop,
173 microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop)
174 storeIops = (microStrUopIop, microStrFpUopIop,
175 microStrDBFpUopIop, microStrDTFpUopIop)
176 for iop in loadIops + storeIops:
177 header_output += MicroMemDeclare.subst(iop)
178 decoder_output += MicroMemConstructor.subst(iop)
179 for iop in loadIops:
180 exec_output += LoadExecute.subst(iop) + \
181 LoadInitiateAcc.subst(iop) + \
182 LoadCompleteAcc.subst(iop)
183 for iop in storeIops:
184 exec_output += StoreExecute.subst(iop) + \
185 StoreInitiateAcc.subst(iop) + \
186 StoreCompleteAcc.subst(iop)
187
188 header_output += MicroMemPairDeclare.subst(microLdr2UopIop)
189 decoder_output += MicroMemPairConstructor.subst(microLdr2UopIop)
190 exec_output += LoadExecute.subst(microLdr2UopIop) + \
191 LoadInitiateAcc.subst(microLdr2UopIop) + \
192 LoadCompleteAcc.subst(microLdr2UopIop)
193 }};
194
195 let {{
196 exec_output = header_output = ''
197
198 eaCode = 'EA = XURa + imm;'
199
200 for size in (1, 2, 3, 4, 6, 8, 12, 16):
201 # Set up the memory access.
202 regs = (size + 3) // 4
203 subst = { "size" : size, "regs" : regs }
204 memDecl = '''
205 union MemUnion {
206 uint8_t bytes[%(size)d];
207 Element elements[%(size)d / sizeof(Element)];
208 uint32_t floatRegBits[%(regs)d];
209 };
210 ''' % subst
211
212 # Do endian conversion for all the elements.
213 convCode = '''
214 const unsigned eCount = sizeof(memUnion.elements) /
215 sizeof(memUnion.elements[0]);
216 if (((CPSR)Cpsr).e) {
217 for (unsigned i = 0; i < eCount; i++) {
218 memUnion.elements[i] = letobe(memUnion.elements[i]);
219 }
220 } else {
221 for (unsigned i = 0; i < eCount; i++) {
222 memUnion.elements[i] = memUnion.elements[i];
223 }
224 }
225 '''
226
227 # Offload everything into registers
228 regSetCode = ''
229 for reg in range(regs):
230 mask = ''
231 if reg == regs - 1:
232 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size))
233 regSetCode += '''
234 FpDestP%(reg)d_uw = letoh(memUnion.floatRegBits[%(reg)d])%(mask)s;
235 ''' % { "reg" : reg, "mask" : mask }
236
237 # Pull everything in from registers
238 regGetCode = ''
239 for reg in range(regs):
240 regGetCode += '''
241 memUnion.floatRegBits[%(reg)d] = htole(FpDestP%(reg)d_uw);
242 ''' % { "reg" : reg }
243
244 loadMemAccCode = convCode + regSetCode
245 storeMemAccCode = regGetCode + convCode
246
247 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst,
248 'MicroLdrNeon%(size)dUop' % subst,
249 'MicroNeonMemOp',
250 { 'mem_decl' : memDecl,
251 'size' : size,
252 'memacc_code' : loadMemAccCode,
253 'ea_code' : simdEnabledCheckCode + eaCode,
254 'predicate_test' : predicateTest },
255 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ])
256 storeIop = InstObjParams('strneon%(size)d_uop' % subst,
257 'MicroStrNeon%(size)dUop' % subst,
258 'MicroNeonMemOp',
259 { 'mem_decl' : memDecl,
260 'size' : size,
261 'memacc_code' : storeMemAccCode,
262 'ea_code' : simdEnabledCheckCode + eaCode,
263 'predicate_test' : predicateTest },
264 [ 'IsMicroop', 'IsMemRef', 'IsStore' ])
265
266 exec_output += NeonLoadExecute.subst(loadIop) + \
267 NeonLoadInitiateAcc.subst(loadIop) + \
268 NeonLoadCompleteAcc.subst(loadIop) + \
269 NeonStoreExecute.subst(storeIop) + \
270 NeonStoreInitiateAcc.subst(storeIop) + \
271 NeonStoreCompleteAcc.subst(storeIop)
272 header_output += MicroNeonMemDeclare.subst(loadIop) + \
273 MicroNeonMemDeclare.subst(storeIop)
274 }};
275
276 let {{
277 exec_output = ''
278 for eSize, type in (1, 'uint8_t'), \
279 (2, 'uint16_t'), \
280 (4, 'uint32_t'), \
281 (8, 'uint64_t'):
282 size = eSize
283 # An instruction handles no more than 16 bytes and no more than
284 # 4 elements, or the number of elements needed to fill 8 or 16 bytes.
285 sizes = set((16, 8))
286 for count in 1, 2, 3, 4:
287 size = count * eSize
288 if size <= 16:
289 sizes.add(size)
290 for size in sizes:
291 substDict = {
292 "class_name" : "MicroLdrNeon%dUop" % size,
293 "targs" : type
294 }
295 exec_output += MicroNeonMemExecDeclare.subst(substDict)
296 substDict["class_name"] = "MicroStrNeon%dUop" % size
297 exec_output += MicroNeonMemExecDeclare.subst(substDict)
298 size += eSize
299 }};
300
301 ////////////////////////////////////////////////////////////////////
302 //
303 // Neon (de)interlacing microops
304 //
305
306 let {{
307 header_output = exec_output = ''
308 for dRegs in (2, 3, 4):
309 loadConv = ''
310 unloadConv = ''
311 for dReg in range(dRegs):
312 loadConv += '''
313 conv1.cRegs[%(sReg0)d] = htole(FpOp1P%(sReg0)d_uw);
314 conv1.cRegs[%(sReg1)d] = htole(FpOp1P%(sReg1)d_uw);
315 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
316 unloadConv += '''
317 FpDestS%(dReg)dP0_uw = letoh(conv2.cRegs[2 * %(dReg)d + 0]);
318 FpDestS%(dReg)dP1_uw = letoh(conv2.cRegs[2 * %(dReg)d + 1]);
319 ''' % { "dReg" : dReg }
320 microDeintNeonCode = '''
321 const unsigned dRegs = %(dRegs)d;
322 const unsigned regs = 2 * dRegs;
323 const unsigned perDReg =
324 (2 * sizeof(uint32_t)) / sizeof(Element);
325 union convStruct {
326 uint32_t cRegs[regs];
327 Element elements[dRegs * perDReg];
328 } conv1, conv2;
329
330 %(loadConv)s
331
332 unsigned srcElem = 0;
333 for (unsigned destOffset = 0;
334 destOffset < perDReg; destOffset++) {
335 for (unsigned dReg = 0; dReg < dRegs; dReg++) {
336 conv2.elements[dReg * perDReg + destOffset] =
337 conv1.elements[srcElem++];
338 }
339 }
340
341 %(unloadConv)s
342 ''' % { "dRegs" : dRegs,
343 "loadConv" : loadConv,
344 "unloadConv" : unloadConv }
345 microDeintNeonIop = \
346 InstObjParams('deintneon%duop' % (dRegs * 2),
347 'MicroDeintNeon%dUop' % (dRegs * 2),
348 'MicroNeonMixOp',
349 { 'predicate_test': predicateTest,
350 'code' : microDeintNeonCode },
351 ['IsMicroop'])
352 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop)
353 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop)
354
355 loadConv = ''
356 unloadConv = ''
357 for dReg in range(dRegs):
358 loadConv += '''
359 conv1.cRegs[2 * %(dReg)d + 0] = htole(FpOp1S%(dReg)dP0_uw);
360 conv1.cRegs[2 * %(dReg)d + 1] = htole(FpOp1S%(dReg)dP1_uw);
361 ''' % { "dReg" : dReg }
362 unloadConv += '''
363 FpDestP%(sReg0)d_uw = letoh(conv2.cRegs[%(sReg0)d]);
364 FpDestP%(sReg1)d_uw = letoh(conv2.cRegs[%(sReg1)d]);
365 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
366 microInterNeonCode = '''
367 const unsigned dRegs = %(dRegs)d;
368 const unsigned regs = 2 * dRegs;
369 const unsigned perDReg =
370 (2 * sizeof(uint32_t)) / sizeof(Element);
371 union convStruct {
372 uint32_t cRegs[regs];
373 Element elements[dRegs * perDReg];
374 } conv1, conv2;
375
376 %(loadConv)s
377
378 unsigned destElem = 0;
379 for (unsigned srcOffset = 0;
380 srcOffset < perDReg; srcOffset++) {
381 for (unsigned dReg = 0; dReg < dRegs; dReg++) {
382 conv2.elements[destElem++] =
383 conv1.elements[dReg * perDReg + srcOffset];
384 }
385 }
386
387 %(unloadConv)s
388 ''' % { "dRegs" : dRegs,
389 "loadConv" : loadConv,
390 "unloadConv" : unloadConv }
391 microInterNeonIop = \
392 InstObjParams('interneon%duop' % (dRegs * 2),
393 'MicroInterNeon%dUop' % (dRegs * 2),
394 'MicroNeonMixOp',
395 { 'predicate_test': predicateTest,
396 'code' : microInterNeonCode },
397 ['IsMicroop'])
398 header_output += MicroNeonMixDeclare.subst(microInterNeonIop)
399 exec_output += MicroNeonMixExecute.subst(microInterNeonIop)
400 }};
401
402 let {{
403 exec_output = ''
404 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'):
405 for dRegs in (2, 3, 4):
406 Name = "MicroDeintNeon%dUop" % (dRegs * 2)
407 substDict = { "class_name" : Name, "targs" : type }
408 exec_output += MicroNeonExecDeclare.subst(substDict)
409 Name = "MicroInterNeon%dUop" % (dRegs * 2)
410 substDict = { "class_name" : Name, "targs" : type }
411 exec_output += MicroNeonExecDeclare.subst(substDict)
412 }};
413
414 ////////////////////////////////////////////////////////////////////
415 //
416 // Neon microops to pack/unpack a single lane
417 //
418
419 let {{
420 header_output = exec_output = ''
421 for sRegs in 1, 2:
422 baseLoadRegs = ''
423 for reg in range(sRegs):
424 baseLoadRegs += '''
425 sourceRegs.fRegs[%(reg0)d] = htole(FpOp1P%(reg0)d_uw);
426 sourceRegs.fRegs[%(reg1)d] = htole(FpOp1P%(reg1)d_uw);
427 ''' % { "reg0" : (2 * reg + 0),
428 "reg1" : (2 * reg + 1) }
429 for dRegs in range(sRegs, 5):
430 unloadRegs = ''
431 loadRegs = baseLoadRegs
432 for reg in range(dRegs):
433 loadRegs += '''
434 destRegs[%(reg)d].fRegs[0] = htole(FpDestS%(reg)dP0_uw);
435 destRegs[%(reg)d].fRegs[1] = htole(FpDestS%(reg)dP1_uw);
436 ''' % { "reg" : reg }
437 unloadRegs += '''
438 FpDestS%(reg)dP0_uw = letoh(destRegs[%(reg)d].fRegs[0]);
439 FpDestS%(reg)dP1_uw = letoh(destRegs[%(reg)d].fRegs[1]);
440 ''' % { "reg" : reg }
441 microUnpackNeonCode = '''
442 const unsigned perDReg = (2 * sizeof(uint32_t)) / sizeof(Element);
443
444 union SourceRegs {
445 uint32_t fRegs[2 * %(sRegs)d];
446 Element elements[%(sRegs)d * perDReg];
447 } sourceRegs;
448
449 union DestReg {
450 uint32_t fRegs[2];
451 Element elements[perDReg];
452 } destRegs[%(dRegs)d];
453
454 %(loadRegs)s
455
456 for (unsigned i = 0; i < %(dRegs)d; i++) {
457 destRegs[i].elements[lane] = sourceRegs.elements[i];
458 }
459
460 %(unloadRegs)s
461 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
462 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
463
464 microUnpackNeonIop = \
465 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2),
466 'MicroUnpackNeon%dto%dUop' %
467 (sRegs * 2, dRegs * 2),
468 'MicroNeonMixLaneOp',
469 { 'predicate_test': predicateTest,
470 'code' : microUnpackNeonCode },
471 ['IsMicroop'])
472 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop)
473 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop)
474
475 for sRegs in 1, 2:
476 loadRegs = ''
477 for reg in range(sRegs):
478 loadRegs += '''
479 sourceRegs.fRegs[%(reg0)d] = htole(FpOp1P%(reg0)d_uw);
480 sourceRegs.fRegs[%(reg1)d] = htole(FpOp1P%(reg1)d_uw);
481 ''' % { "reg0" : (2 * reg + 0),
482 "reg1" : (2 * reg + 1) }
483 for dRegs in range(sRegs, 5):
484 unloadRegs = ''
485 for reg in range(dRegs):
486 unloadRegs += '''
487 FpDestS%(reg)dP0_uw = letoh(destRegs[%(reg)d].fRegs[0]);
488 FpDestS%(reg)dP1_uw = letoh(destRegs[%(reg)d].fRegs[1]);
489 ''' % { "reg" : reg }
490 microUnpackAllNeonCode = '''
491 const unsigned perDReg = (2 * sizeof(uint32_t)) / sizeof(Element);
492
493 union SourceRegs {
494 uint32_t fRegs[2 * %(sRegs)d];
495 Element elements[%(sRegs)d * perDReg];
496 } sourceRegs;
497
498 union DestReg {
499 uint32_t fRegs[2];
500 Element elements[perDReg];
501 } destRegs[%(dRegs)d];
502
503 %(loadRegs)s
504
505 for (unsigned i = 0; i < %(dRegs)d; i++) {
506 for (unsigned j = 0; j < perDReg; j++)
507 destRegs[i].elements[j] = sourceRegs.elements[i];
508 }
509
510 %(unloadRegs)s
511 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
512 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
513
514 microUnpackAllNeonIop = \
515 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2),
516 'MicroUnpackAllNeon%dto%dUop' %
517 (sRegs * 2, dRegs * 2),
518 'MicroNeonMixOp',
519 { 'predicate_test': predicateTest,
520 'code' : microUnpackAllNeonCode },
521 ['IsMicroop'])
522 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop)
523 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop)
524
525 for dRegs in 1, 2:
526 unloadRegs = ''
527 for reg in range(dRegs):
528 unloadRegs += '''
529 FpDestP%(reg0)d_uw = letoh(destRegs.fRegs[%(reg0)d]);
530 FpDestP%(reg1)d_uw = letoh(destRegs.fRegs[%(reg1)d]);
531 ''' % { "reg0" : (2 * reg + 0),
532 "reg1" : (2 * reg + 1) }
533 for sRegs in range(dRegs, 5):
534 loadRegs = ''
535 for reg in range(sRegs):
536 loadRegs += '''
537 sourceRegs[%(reg)d].fRegs[0] = htole(FpOp1S%(reg)dP0_uw);
538 sourceRegs[%(reg)d].fRegs[1] = htole(FpOp1S%(reg)dP1_uw);
539 ''' % { "reg" : reg }
540 microPackNeonCode = '''
541 const unsigned perDReg =
542 (2 * sizeof(uint32_t)) / sizeof(Element);
543
544 union SourceReg {
545 uint32_t fRegs[2];
546 Element elements[perDReg];
547 } sourceRegs[%(sRegs)d];
548
549 union DestRegs {
550 uint32_t fRegs[2 * %(dRegs)d];
551 Element elements[%(dRegs)d * perDReg];
552 } destRegs;
553
554 %(loadRegs)s
555
556 for (unsigned i = 0; i < %(sRegs)d; i++) {
557 destRegs.elements[i] = sourceRegs[i].elements[lane];
558 }
559 for (unsigned i = %(sRegs)d; i < %(dRegs)d * perDReg; ++i) {
560 destRegs.elements[i] = 0;
561 }
562
563 %(unloadRegs)s
564 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
565 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
566
567 microPackNeonIop = \
568 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2),
569 'MicroPackNeon%dto%dUop' %
570 (sRegs * 2, dRegs * 2),
571 'MicroNeonMixLaneOp',
572 { 'predicate_test': predicateTest,
573 'code' : microPackNeonCode },
574 ['IsMicroop'])
575 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop)
576 exec_output += MicroNeonMixExecute.subst(microPackNeonIop)
577 }};
578
579 let {{
580 exec_output = ''
581 for typeSize in (8, 16, 32):
582 for sRegs in 1, 2:
583 for dRegs in range(sRegs, min(sRegs * 64 / typeSize + 1, 5)):
584 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop",
585 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop",
586 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"):
587 Name = format % { "sRegs" : sRegs * 2,
588 "dRegs" : dRegs * 2 }
589 substDict = { "class_name" : Name,
590 "targs" : "uint%d_t" % typeSize }
591 exec_output += MicroNeonExecDeclare.subst(substDict)
592 }};
593
594 ////////////////////////////////////////////////////////////////////
595 //
596 // Integer = Integer op Immediate microops
597 //
598
599 let {{
600 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
601 'MicroIntImmOp',
602 {'code': 'URa = URb + imm;',
603 'predicate_test': predicateTest},
604 ['IsMicroop'])
605
606 microAddUopCode = '''
607 URa = URb + shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC);
608 '''
609
610 microAddXiUopIop = InstObjParams('addxi_uop', 'MicroAddXiUop',
611 'MicroIntImmXOp',
612 'XURa = XURb + imm;',
613 ['IsMicroop'])
614
615 microAddXiSpAlignUopIop = InstObjParams('addxi_uop', 'MicroAddXiSpAlignUop',
616 'MicroIntImmXOp', '''
617 if (isSP((IntRegIndex) urb) && bits(XURb, 3, 0) &&
618 SPAlignmentCheckEnabled(xc->tcBase())) {
619 return std::make_shared<SPAlignmentFault>();
620 }
621 XURa = XURb + imm;
622 ''', ['IsMicroop'])
623
624 microAddXERegUopIop = InstObjParams('addxr_uop', 'MicroAddXERegUop',
625 'MicroIntRegXOp',
626 'XURa = XURb + ' + \
627 'extendReg64(XURc, type, shiftAmt, 64);',
628 ['IsMicroop'])
629
630 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
631 'MicroIntRegOp',
632 {'code': microAddUopCode,
633 'predicate_test': pickPredicate(microAddUopCode)},
634 ['IsMicroop'])
635
636 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
637 'MicroIntImmOp',
638 {'code': 'URa = URb - imm;',
639 'predicate_test': predicateTest},
640 ['IsMicroop'])
641
642 microSubXiUopIop = InstObjParams('subxi_uop', 'MicroSubXiUop',
643 'MicroIntImmXOp',
644 'XURa = XURb - imm;',
645 ['IsMicroop'])
646
647 microSubUopCode = '''
648 URa = URb - shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC);
649 '''
650 microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop',
651 'MicroIntRegOp',
652 {'code': microSubUopCode,
653 'predicate_test': pickPredicate(microSubUopCode)},
654 ['IsMicroop'])
655
656 microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov',
657 'MicroIntMov',
658 {'code': 'IWRa = URb;',
659 'predicate_test': predicateTest},
660 ['IsMicroop'])
661
662 microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet',
663 'MicroIntMov',
664 {'code': microRetUopCode % 'URb',
665 'predicate_test': predicateTest},
666 ['IsMicroop', 'IsNonSpeculative',
667 'IsSerializeAfter', 'IsSquashAfter'])
668
669 setPCCPSRDecl = '''
670 CPSR cpsrOrCondCodes = URc;
671 SCTLR sctlr = Sctlr;
672 pNPC = URa;
673 CPSR new_cpsr =
674 cpsrWriteByInstr(cpsrOrCondCodes, URb, Scr, Nsacr,
675 0xF, true, sctlr.nmfi, xc->tcBase());
676 Cpsr = ~CondCodesMask & new_cpsr;
677 NextThumb = new_cpsr.t;
678 NextJazelle = new_cpsr.j;
679 NextItState = ((((CPSR)URb).it2 << 2) & 0xFC)
680 | (((CPSR)URb).it1 & 0x3);
681 CondCodesNZ = new_cpsr.nz;
682 CondCodesC = new_cpsr.c;
683 CondCodesV = new_cpsr.v;
684 CondCodesGE = new_cpsr.ge;
685 '''
686
687 microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR',
688 'MicroSetPCCPSR',
689 {'code': setPCCPSRDecl,
690 'predicate_test': predicateTest},
691 ['IsMicroop', 'IsSerializeAfter'])
692
693 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
694 MicroIntImmDeclare.subst(microAddXiUopIop) + \
695 MicroIntImmDeclare.subst(microAddXiSpAlignUopIop) + \
696 MicroIntImmDeclare.subst(microSubiUopIop) + \
697 MicroIntImmDeclare.subst(microSubXiUopIop) + \
698 MicroIntRegDeclare.subst(microAddUopIop) + \
699 MicroIntRegDeclare.subst(microSubUopIop) + \
700 MicroIntXERegDeclare.subst(microAddXERegUopIop) + \
701 MicroIntMovDeclare.subst(microUopRegMovIop) + \
702 MicroIntMovDeclare.subst(microUopRegMovRetIop) + \
703 MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop)
704
705 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
706 MicroIntImmXConstructor.subst(microAddXiUopIop) + \
707 MicroIntImmXConstructor.subst(microAddXiSpAlignUopIop) + \
708 MicroIntImmConstructor.subst(microSubiUopIop) + \
709 MicroIntImmXConstructor.subst(microSubXiUopIop) + \
710 MicroIntRegConstructor.subst(microAddUopIop) + \
711 MicroIntRegConstructor.subst(microSubUopIop) + \
712 MicroIntXERegConstructor.subst(microAddXERegUopIop) + \
713 MicroIntMovConstructor.subst(microUopRegMovIop) + \
714 MicroIntMovConstructor.subst(microUopRegMovRetIop) + \
715 MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop)
716
717 exec_output = PredOpExecute.subst(microAddiUopIop) + \
718 BasicExecute.subst(microAddXiUopIop) + \
719 BasicExecute.subst(microAddXiSpAlignUopIop) + \
720 PredOpExecute.subst(microSubiUopIop) + \
721 BasicExecute.subst(microSubXiUopIop) + \
722 PredOpExecute.subst(microAddUopIop) + \
723 PredOpExecute.subst(microSubUopIop) + \
724 BasicExecute.subst(microAddXERegUopIop) + \
725 PredOpExecute.subst(microUopRegMovIop) + \
726 PredOpExecute.subst(microUopRegMovRetIop) + \
727 PredOpExecute.subst(microUopSetPCCPSRIop)
728
729 }};
730
731 let {{
732 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", [])
733 header_output = MacroMemDeclare.subst(iop)
734 decoder_output = MacroMemConstructor.subst(iop)
735
736 iop = InstObjParams("ldpstp", "LdpStp", 'PairMemOp', "", [])
737 header_output += PairMemDeclare.subst(iop)
738 decoder_output += PairMemConstructor.subst(iop)
739
740 iopImm = InstObjParams("bigfpmemimm", "BigFpMemImm", "BigFpMemImmOp", "")
741 iopPre = InstObjParams("bigfpmempre", "BigFpMemPre", "BigFpMemPreOp", "")
742 iopPost = InstObjParams("bigfpmempost", "BigFpMemPost", "BigFpMemPostOp", "")
743 for iop in (iopImm, iopPre, iopPost):
744 header_output += BigFpMemImmDeclare.subst(iop)
745 decoder_output += BigFpMemImmConstructor.subst(iop)
746
747 iop = InstObjParams("bigfpmemreg", "BigFpMemReg", "BigFpMemRegOp", "")
748 header_output += BigFpMemRegDeclare.subst(iop)
749 decoder_output += BigFpMemRegConstructor.subst(iop)
750
751 iop = InstObjParams("bigfpmemlit", "BigFpMemLit", "BigFpMemLitOp", "")
752 header_output += BigFpMemLitDeclare.subst(iop)
753 decoder_output += BigFpMemLitConstructor.subst(iop)
754
755 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", [])
756 header_output += VMemMultDeclare.subst(iop)
757 decoder_output += VMemMultConstructor.subst(iop)
758
759 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", [])
760 header_output += VMemSingleDeclare.subst(iop)
761 decoder_output += VMemSingleConstructor.subst(iop)
762
763 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", [])
764 header_output += VMemMultDeclare.subst(iop)
765 decoder_output += VMemMultConstructor.subst(iop)
766
767 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", [])
768 header_output += VMemSingleDeclare.subst(iop)
769 decoder_output += VMemSingleConstructor.subst(iop)
770
771 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", [])
772 header_output += MacroVFPMemDeclare.subst(vfpIop)
773 decoder_output += MacroVFPMemConstructor.subst(vfpIop)
774 }};