macromem.isa (7644:62873d5c2bfc) macromem.isa (7646:a444dbee8c07)
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010 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// Authors: Stephen Hines
42// Gabe Black
43
44////////////////////////////////////////////////////////////////////
45//
46// Load/store microops
47//
48
49let {{
50 microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
51 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
52 'MicroMemOp',
53 {'memacc_code': microLdrUopCode,
54 'ea_code': 'EA = Rb + (up ? imm : -imm);',
55 'predicate_test': predicateTest},
56 ['IsMicroop'])
57
58 microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
59 microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop',
60 'MicroMemOp',
61 {'memacc_code': microLdrFpUopCode,
62 'ea_code': vfpEnabledCheckCode +
63 'EA = Rb + (up ? imm : -imm);',
64 'predicate_test': predicateTest},
65 ['IsMicroop'])
66
67 microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
68 microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop',
69 'MicroMemOp',
70 {'memacc_code': microLdrFpUopCode,
71 'ea_code': vfpEnabledCheckCode + '''
72 EA = Rb + (up ? imm : -imm) +
73 (((CPSR)Cpsr).e ? 4 : 0);
74 ''',
75 'predicate_test': predicateTest},
76 ['IsMicroop'])
77
78 microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
79 microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop',
80 'MicroMemOp',
81 {'memacc_code': microLdrFpUopCode,
82 'ea_code': vfpEnabledCheckCode + '''
83 EA = Rb + (up ? imm : -imm) -
84 (((CPSR)Cpsr).e ? 4 : 0);
85 ''',
86 'predicate_test': predicateTest},
87 ['IsMicroop'])
88
89 microLdrRetUopCode = '''
90 CPSR cpsr = Cpsr;
91 SCTLR sctlr = Sctlr;
92 uint32_t newCpsr =
93 cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
94 Cpsr = ~CondCodesMask & newCpsr;
95 CondCodes = CondCodesMask & newCpsr;
96 IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
97 '''
98 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
99 'MicroMemOp',
100 {'memacc_code': microLdrRetUopCode,
101 'ea_code':
102 'EA = Rb + (up ? imm : -imm);',
103 'predicate_test': condPredicateTest},
104 ['IsMicroop'])
105
106 microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);"
107 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
108 'MicroMemOp',
109 {'memacc_code': microStrUopCode,
110 'postacc_code': "",
111 'ea_code': 'EA = Rb + (up ? imm : -imm);',
112 'predicate_test': predicateTest},
113 ['IsMicroop'])
114
115 microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
116 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
117 'MicroMemOp',
118 {'memacc_code': microStrFpUopCode,
119 'postacc_code': "",
120 'ea_code': vfpEnabledCheckCode +
121 'EA = Rb + (up ? imm : -imm);',
122 'predicate_test': predicateTest},
123 ['IsMicroop'])
124
125 microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
126 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop',
127 'MicroMemOp',
128 {'memacc_code': microStrFpUopCode,
129 'postacc_code': "",
130 'ea_code': vfpEnabledCheckCode + '''
131 EA = Rb + (up ? imm : -imm) +
132 (((CPSR)Cpsr).e ? 4 : 0);
133 ''',
134 'predicate_test': predicateTest},
135 ['IsMicroop'])
136
137 microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
138 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop',
139 'MicroMemOp',
140 {'memacc_code': microStrFpUopCode,
141 'postacc_code': "",
142 'ea_code': vfpEnabledCheckCode + '''
143 EA = Rb + (up ? imm : -imm) -
144 (((CPSR)Cpsr).e ? 4 : 0);
145 ''',
146 'predicate_test': predicateTest},
147 ['IsMicroop'])
148
149 header_output = decoder_output = exec_output = ''
150
151 loadIops = (microLdrUopIop, microLdrRetUopIop,
152 microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop)
153 storeIops = (microStrUopIop, microStrFpUopIop,
154 microStrDBFpUopIop, microStrDTFpUopIop)
155 for iop in loadIops + storeIops:
156 header_output += MicroMemDeclare.subst(iop)
157 decoder_output += MicroMemConstructor.subst(iop)
158 for iop in loadIops:
159 exec_output += LoadExecute.subst(iop) + \
160 LoadInitiateAcc.subst(iop) + \
161 LoadCompleteAcc.subst(iop)
162 for iop in storeIops:
163 exec_output += StoreExecute.subst(iop) + \
164 StoreInitiateAcc.subst(iop) + \
165 StoreCompleteAcc.subst(iop)
166}};
167
168let {{
169 exec_output = header_output = ''
170
171 eaCode = 'EA = Ra + imm;'
172
173 for size in (1, 2, 3, 4, 6, 8, 12, 16):
174 # Set up the memory access.
175 regs = (size + 3) // 4
176 subst = { "size" : size, "regs" : regs }
177 memDecl = '''
178 union MemUnion {
179 uint8_t bytes[%(size)d];
180 Element elements[%(size)d / sizeof(Element)];
181 uint32_t floatRegBits[%(regs)d];
182 };
183 ''' % subst
184
185 # Do endian conversion for all the elements.
186 convCode = '''
187 const unsigned eCount = sizeof(memUnion.elements) /
188 sizeof(memUnion.elements[0]);
189 if (((CPSR)Cpsr).e) {
190 for (unsigned i = 0; i < eCount; i++) {
191 memUnion.elements[i] = gtobe(memUnion.elements[i]);
192 }
193 } else {
194 for (unsigned i = 0; i < eCount; i++) {
195 memUnion.elements[i] = gtole(memUnion.elements[i]);
196 }
197 }
198 '''
199
200 # Offload everything into registers
201 regSetCode = ''
202 for reg in range(regs):
203 mask = ''
204 if reg == regs - 1:
205 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size))
206 regSetCode += '''
207 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s;
208 ''' % { "reg" : reg, "mask" : mask }
209
210 # Pull everything in from registers
211 regGetCode = ''
212 for reg in range(regs):
213 regGetCode += '''
214 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw);
215 ''' % { "reg" : reg }
216
217 loadMemAccCode = convCode + regSetCode
218 storeMemAccCode = regGetCode + convCode
219
220 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst,
221 'MicroLdrNeon%(size)dUop' % subst,
222 'MicroNeonMemOp',
223 { 'mem_decl' : memDecl,
224 'size' : size,
225 'memacc_code' : loadMemAccCode,
226 'ea_code' : simdEnabledCheckCode + eaCode,
227 'predicate_test' : predicateTest },
228 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ])
229 storeIop = InstObjParams('strneon%(size)d_uop' % subst,
230 'MicroStrNeon%(size)dUop' % subst,
231 'MicroNeonMemOp',
232 { 'mem_decl' : memDecl,
233 'size' : size,
234 'memacc_code' : storeMemAccCode,
235 'ea_code' : simdEnabledCheckCode + eaCode,
236 'predicate_test' : predicateTest },
237 [ 'IsMicroop', 'IsMemRef', 'IsStore' ])
238
239 exec_output += NeonLoadExecute.subst(loadIop) + \
240 NeonLoadInitiateAcc.subst(loadIop) + \
241 NeonLoadCompleteAcc.subst(loadIop) + \
242 NeonStoreExecute.subst(storeIop) + \
243 NeonStoreInitiateAcc.subst(storeIop) + \
244 NeonStoreCompleteAcc.subst(storeIop)
245 header_output += MicroNeonMemDeclare.subst(loadIop) + \
246 MicroNeonMemDeclare.subst(storeIop)
247}};
248
249let {{
250 exec_output = ''
251 for eSize, type in (1, 'uint8_t'), \
252 (2, 'uint16_t'), \
253 (4, 'uint32_t'), \
254 (8, 'uint64_t'):
255 size = eSize
256 # An instruction handles no more than 16 bytes and no more than
257 # 4 elements, or the number of elements needed to fill 8 or 16 bytes.
258 sizes = set((16, 8))
259 for count in 1, 2, 3, 4:
260 size = count * eSize
261 if size <= 16:
262 sizes.add(size)
263 for size in sizes:
264 substDict = {
265 "class_name" : "MicroLdrNeon%dUop" % size,
266 "targs" : type
267 }
268 exec_output += MicroNeonMemExecDeclare.subst(substDict)
269 substDict["class_name"] = "MicroStrNeon%dUop" % size
270 exec_output += MicroNeonMemExecDeclare.subst(substDict)
271 size += eSize
272}};
273
274////////////////////////////////////////////////////////////////////
275//
276// Neon (de)interlacing microops
277//
278
279let {{
280 header_output = exec_output = ''
281 for dRegs in (2, 3, 4):
282 loadConv = ''
283 unloadConv = ''
284 for dReg in range(dRegs):
285 loadConv += '''
286 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw);
287 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw);
288 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
289 unloadConv += '''
290 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]);
291 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]);
292 ''' % { "dReg" : dReg }
293 microDeintNeonCode = '''
294 const unsigned dRegs = %(dRegs)d;
295 const unsigned regs = 2 * dRegs;
296 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
297 sizeof(Element);
298 union convStruct {
299 FloatRegBits cRegs[regs];
300 Element elements[dRegs * perDReg];
301 } conv1, conv2;
302
303 %(loadConv)s
304
305 unsigned srcElem = 0;
306 for (unsigned destOffset = 0;
307 destOffset < perDReg; destOffset++) {
308 for (unsigned dReg = 0; dReg < dRegs; dReg++) {
309 conv2.elements[dReg * perDReg + destOffset] =
310 conv1.elements[srcElem++];
311 }
312 }
313
314 %(unloadConv)s
315 ''' % { "dRegs" : dRegs,
316 "loadConv" : loadConv,
317 "unloadConv" : unloadConv }
318 microDeintNeonIop = \
319 InstObjParams('deintneon%duop' % (dRegs * 2),
320 'MicroDeintNeon%dUop' % (dRegs * 2),
321 'MicroNeonMixOp',
322 { 'predicate_test': predicateTest,
323 'code' : microDeintNeonCode },
324 ['IsMicroop'])
325 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop)
326 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop)
327
328 loadConv = ''
329 unloadConv = ''
330 for dReg in range(dRegs):
331 loadConv += '''
332 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw);
333 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw);
334 ''' % { "dReg" : dReg }
335 unloadConv += '''
336 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]);
337 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]);
338 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
339 microInterNeonCode = '''
340 const unsigned dRegs = %(dRegs)d;
341 const unsigned regs = 2 * dRegs;
342 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
343 sizeof(Element);
344 union convStruct {
345 FloatRegBits cRegs[regs];
346 Element elements[dRegs * perDReg];
347 } conv1, conv2;
348
349 %(loadConv)s
350
351 unsigned destElem = 0;
352 for (unsigned srcOffset = 0;
353 srcOffset < perDReg; srcOffset++) {
354 for (unsigned dReg = 0; dReg < dRegs; dReg++) {
355 conv2.elements[destElem++] =
356 conv1.elements[dReg * perDReg + srcOffset];
357 }
358 }
359
360 %(unloadConv)s
361 ''' % { "dRegs" : dRegs,
362 "loadConv" : loadConv,
363 "unloadConv" : unloadConv }
364 microInterNeonIop = \
365 InstObjParams('interneon%duop' % (dRegs * 2),
366 'MicroInterNeon%dUop' % (dRegs * 2),
367 'MicroNeonMixOp',
368 { 'predicate_test': predicateTest,
369 'code' : microInterNeonCode },
370 ['IsMicroop'])
371 header_output += MicroNeonMixDeclare.subst(microInterNeonIop)
372 exec_output += MicroNeonMixExecute.subst(microInterNeonIop)
373}};
374
375let {{
376 exec_output = ''
377 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'):
378 for dRegs in (2, 3, 4):
379 Name = "MicroDeintNeon%dUop" % (dRegs * 2)
380 substDict = { "class_name" : Name, "targs" : type }
381 exec_output += MicroNeonExecDeclare.subst(substDict)
382 Name = "MicroInterNeon%dUop" % (dRegs * 2)
383 substDict = { "class_name" : Name, "targs" : type }
384 exec_output += MicroNeonExecDeclare.subst(substDict)
385}};
386
387////////////////////////////////////////////////////////////////////
388//
389// Neon microops to pack/unpack a single lane
390//
391
392let {{
393 header_output = exec_output = ''
394 for sRegs in 1, 2:
395 baseLoadRegs = ''
396 for reg in range(sRegs):
397 baseLoadRegs += '''
398 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw);
399 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw);
400 ''' % { "reg0" : (2 * reg + 0),
401 "reg1" : (2 * reg + 1) }
402 for dRegs in range(sRegs, 5):
403 unloadRegs = ''
404 loadRegs = baseLoadRegs
405 for reg in range(dRegs):
406 loadRegs += '''
407 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw);
408 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw);
409 ''' % { "reg" : reg }
410 unloadRegs += '''
411 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]);
412 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]);
413 ''' % { "reg" : reg }
414 microUnpackNeonCode = '''
415 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
416 sizeof(Element);
417
418 union SourceRegs {
419 FloatRegBits fRegs[2 * %(sRegs)d];
420 Element elements[%(sRegs)d * perDReg];
421 } sourceRegs;
422
423 union DestReg {
424 FloatRegBits fRegs[2];
425 Element elements[perDReg];
426 } destRegs[%(dRegs)d];
427
428 %(loadRegs)s
429
430 for (unsigned i = 0; i < %(dRegs)d; i++) {
431 destRegs[i].elements[lane] = sourceRegs.elements[i];
432 }
433
434 %(unloadRegs)s
435 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
436 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
437
438 microUnpackNeonIop = \
439 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2),
440 'MicroUnpackNeon%dto%dUop' %
441 (sRegs * 2, dRegs * 2),
442 'MicroNeonMixLaneOp',
443 { 'predicate_test': predicateTest,
444 'code' : microUnpackNeonCode },
445 ['IsMicroop'])
446 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop)
447 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop)
448
449 for sRegs in 1, 2:
450 loadRegs = ''
451 for reg in range(sRegs):
452 loadRegs += '''
453 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw);
454 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw);
455 ''' % { "reg0" : (2 * reg + 0),
456 "reg1" : (2 * reg + 1) }
457 for dRegs in range(sRegs, 5):
458 unloadRegs = ''
459 for reg in range(dRegs):
460 unloadRegs += '''
461 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]);
462 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]);
463 ''' % { "reg" : reg }
464 microUnpackAllNeonCode = '''
465 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
466 sizeof(Element);
467
468 union SourceRegs {
469 FloatRegBits fRegs[2 * %(sRegs)d];
470 Element elements[%(sRegs)d * perDReg];
471 } sourceRegs;
472
473 union DestReg {
474 FloatRegBits fRegs[2];
475 Element elements[perDReg];
476 } destRegs[%(dRegs)d];
477
478 %(loadRegs)s
479
480 for (unsigned i = 0; i < %(dRegs)d; i++) {
481 for (unsigned j = 0; j < perDReg; j++)
482 destRegs[i].elements[j] = sourceRegs.elements[i];
483 }
484
485 %(unloadRegs)s
486 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
487 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
488
489 microUnpackAllNeonIop = \
490 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2),
491 'MicroUnpackAllNeon%dto%dUop' %
492 (sRegs * 2, dRegs * 2),
493 'MicroNeonMixOp',
494 { 'predicate_test': predicateTest,
495 'code' : microUnpackAllNeonCode },
496 ['IsMicroop'])
497 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop)
498 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop)
499
500 for dRegs in 1, 2:
501 unloadRegs = ''
502 for reg in range(dRegs):
503 unloadRegs += '''
504 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]);
505 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]);
506 ''' % { "reg0" : (2 * reg + 0),
507 "reg1" : (2 * reg + 1) }
508 for sRegs in range(dRegs, 5):
509 loadRegs = ''
510 for reg in range(sRegs):
511 loadRegs += '''
512 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw);
513 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw);
514 ''' % { "reg" : reg }
515 microPackNeonCode = '''
516 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
517 sizeof(Element);
518
519 union SourceReg {
520 FloatRegBits fRegs[2];
521 Element elements[perDReg];
522 } sourceRegs[%(sRegs)d];
523
524 union DestRegs {
525 FloatRegBits fRegs[2 * %(dRegs)d];
526 Element elements[%(dRegs)d * perDReg];
527 } destRegs;
528
529 %(loadRegs)s
530
531 for (unsigned i = 0; i < %(sRegs)d; i++) {
532 destRegs.elements[i] = sourceRegs[i].elements[lane];
533 }
534
535 %(unloadRegs)s
536 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
537 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
538
539 microPackNeonIop = \
540 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2),
541 'MicroPackNeon%dto%dUop' %
542 (sRegs * 2, dRegs * 2),
543 'MicroNeonMixLaneOp',
544 { 'predicate_test': predicateTest,
545 'code' : microPackNeonCode },
546 ['IsMicroop'])
547 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop)
548 exec_output += MicroNeonMixExecute.subst(microPackNeonIop)
549}};
550
551let {{
552 exec_output = ''
553 for type in ('uint8_t', 'uint16_t', 'uint32_t'):
554 for sRegs in 1, 2:
555 for dRegs in range(sRegs, 5):
556 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop",
557 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop",
558 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"):
559 Name = format % { "sRegs" : sRegs * 2,
560 "dRegs" : dRegs * 2 }
561 substDict = { "class_name" : Name, "targs" : type }
562 exec_output += MicroNeonExecDeclare.subst(substDict)
563}};
564
565////////////////////////////////////////////////////////////////////
566//
567// Integer = Integer op Immediate microops
568//
569
570let {{
571 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
572 'MicroIntImmOp',
573 {'code': 'Ra = Rb + imm;',
574 'predicate_test': predicateTest},
575 ['IsMicroop'])
576
577 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010 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// Authors: Stephen Hines
42// Gabe Black
43
44////////////////////////////////////////////////////////////////////
45//
46// Load/store microops
47//
48
49let {{
50 microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
51 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop',
52 'MicroMemOp',
53 {'memacc_code': microLdrUopCode,
54 'ea_code': 'EA = Rb + (up ? imm : -imm);',
55 'predicate_test': predicateTest},
56 ['IsMicroop'])
57
58 microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
59 microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop',
60 'MicroMemOp',
61 {'memacc_code': microLdrFpUopCode,
62 'ea_code': vfpEnabledCheckCode +
63 'EA = Rb + (up ? imm : -imm);',
64 'predicate_test': predicateTest},
65 ['IsMicroop'])
66
67 microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
68 microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop',
69 'MicroMemOp',
70 {'memacc_code': microLdrFpUopCode,
71 'ea_code': vfpEnabledCheckCode + '''
72 EA = Rb + (up ? imm : -imm) +
73 (((CPSR)Cpsr).e ? 4 : 0);
74 ''',
75 'predicate_test': predicateTest},
76 ['IsMicroop'])
77
78 microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);"
79 microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop',
80 'MicroMemOp',
81 {'memacc_code': microLdrFpUopCode,
82 'ea_code': vfpEnabledCheckCode + '''
83 EA = Rb + (up ? imm : -imm) -
84 (((CPSR)Cpsr).e ? 4 : 0);
85 ''',
86 'predicate_test': predicateTest},
87 ['IsMicroop'])
88
89 microLdrRetUopCode = '''
90 CPSR cpsr = Cpsr;
91 SCTLR sctlr = Sctlr;
92 uint32_t newCpsr =
93 cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
94 Cpsr = ~CondCodesMask & newCpsr;
95 CondCodes = CondCodesMask & newCpsr;
96 IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
97 '''
98 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
99 'MicroMemOp',
100 {'memacc_code': microLdrRetUopCode,
101 'ea_code':
102 'EA = Rb + (up ? imm : -imm);',
103 'predicate_test': condPredicateTest},
104 ['IsMicroop'])
105
106 microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);"
107 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop',
108 'MicroMemOp',
109 {'memacc_code': microStrUopCode,
110 'postacc_code': "",
111 'ea_code': 'EA = Rb + (up ? imm : -imm);',
112 'predicate_test': predicateTest},
113 ['IsMicroop'])
114
115 microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
116 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop',
117 'MicroMemOp',
118 {'memacc_code': microStrFpUopCode,
119 'postacc_code': "",
120 'ea_code': vfpEnabledCheckCode +
121 'EA = Rb + (up ? imm : -imm);',
122 'predicate_test': predicateTest},
123 ['IsMicroop'])
124
125 microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
126 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop',
127 'MicroMemOp',
128 {'memacc_code': microStrFpUopCode,
129 'postacc_code': "",
130 'ea_code': vfpEnabledCheckCode + '''
131 EA = Rb + (up ? imm : -imm) +
132 (((CPSR)Cpsr).e ? 4 : 0);
133 ''',
134 'predicate_test': predicateTest},
135 ['IsMicroop'])
136
137 microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);"
138 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop',
139 'MicroMemOp',
140 {'memacc_code': microStrFpUopCode,
141 'postacc_code': "",
142 'ea_code': vfpEnabledCheckCode + '''
143 EA = Rb + (up ? imm : -imm) -
144 (((CPSR)Cpsr).e ? 4 : 0);
145 ''',
146 'predicate_test': predicateTest},
147 ['IsMicroop'])
148
149 header_output = decoder_output = exec_output = ''
150
151 loadIops = (microLdrUopIop, microLdrRetUopIop,
152 microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop)
153 storeIops = (microStrUopIop, microStrFpUopIop,
154 microStrDBFpUopIop, microStrDTFpUopIop)
155 for iop in loadIops + storeIops:
156 header_output += MicroMemDeclare.subst(iop)
157 decoder_output += MicroMemConstructor.subst(iop)
158 for iop in loadIops:
159 exec_output += LoadExecute.subst(iop) + \
160 LoadInitiateAcc.subst(iop) + \
161 LoadCompleteAcc.subst(iop)
162 for iop in storeIops:
163 exec_output += StoreExecute.subst(iop) + \
164 StoreInitiateAcc.subst(iop) + \
165 StoreCompleteAcc.subst(iop)
166}};
167
168let {{
169 exec_output = header_output = ''
170
171 eaCode = 'EA = Ra + imm;'
172
173 for size in (1, 2, 3, 4, 6, 8, 12, 16):
174 # Set up the memory access.
175 regs = (size + 3) // 4
176 subst = { "size" : size, "regs" : regs }
177 memDecl = '''
178 union MemUnion {
179 uint8_t bytes[%(size)d];
180 Element elements[%(size)d / sizeof(Element)];
181 uint32_t floatRegBits[%(regs)d];
182 };
183 ''' % subst
184
185 # Do endian conversion for all the elements.
186 convCode = '''
187 const unsigned eCount = sizeof(memUnion.elements) /
188 sizeof(memUnion.elements[0]);
189 if (((CPSR)Cpsr).e) {
190 for (unsigned i = 0; i < eCount; i++) {
191 memUnion.elements[i] = gtobe(memUnion.elements[i]);
192 }
193 } else {
194 for (unsigned i = 0; i < eCount; i++) {
195 memUnion.elements[i] = gtole(memUnion.elements[i]);
196 }
197 }
198 '''
199
200 # Offload everything into registers
201 regSetCode = ''
202 for reg in range(regs):
203 mask = ''
204 if reg == regs - 1:
205 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size))
206 regSetCode += '''
207 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s;
208 ''' % { "reg" : reg, "mask" : mask }
209
210 # Pull everything in from registers
211 regGetCode = ''
212 for reg in range(regs):
213 regGetCode += '''
214 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw);
215 ''' % { "reg" : reg }
216
217 loadMemAccCode = convCode + regSetCode
218 storeMemAccCode = regGetCode + convCode
219
220 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst,
221 'MicroLdrNeon%(size)dUop' % subst,
222 'MicroNeonMemOp',
223 { 'mem_decl' : memDecl,
224 'size' : size,
225 'memacc_code' : loadMemAccCode,
226 'ea_code' : simdEnabledCheckCode + eaCode,
227 'predicate_test' : predicateTest },
228 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ])
229 storeIop = InstObjParams('strneon%(size)d_uop' % subst,
230 'MicroStrNeon%(size)dUop' % subst,
231 'MicroNeonMemOp',
232 { 'mem_decl' : memDecl,
233 'size' : size,
234 'memacc_code' : storeMemAccCode,
235 'ea_code' : simdEnabledCheckCode + eaCode,
236 'predicate_test' : predicateTest },
237 [ 'IsMicroop', 'IsMemRef', 'IsStore' ])
238
239 exec_output += NeonLoadExecute.subst(loadIop) + \
240 NeonLoadInitiateAcc.subst(loadIop) + \
241 NeonLoadCompleteAcc.subst(loadIop) + \
242 NeonStoreExecute.subst(storeIop) + \
243 NeonStoreInitiateAcc.subst(storeIop) + \
244 NeonStoreCompleteAcc.subst(storeIop)
245 header_output += MicroNeonMemDeclare.subst(loadIop) + \
246 MicroNeonMemDeclare.subst(storeIop)
247}};
248
249let {{
250 exec_output = ''
251 for eSize, type in (1, 'uint8_t'), \
252 (2, 'uint16_t'), \
253 (4, 'uint32_t'), \
254 (8, 'uint64_t'):
255 size = eSize
256 # An instruction handles no more than 16 bytes and no more than
257 # 4 elements, or the number of elements needed to fill 8 or 16 bytes.
258 sizes = set((16, 8))
259 for count in 1, 2, 3, 4:
260 size = count * eSize
261 if size <= 16:
262 sizes.add(size)
263 for size in sizes:
264 substDict = {
265 "class_name" : "MicroLdrNeon%dUop" % size,
266 "targs" : type
267 }
268 exec_output += MicroNeonMemExecDeclare.subst(substDict)
269 substDict["class_name"] = "MicroStrNeon%dUop" % size
270 exec_output += MicroNeonMemExecDeclare.subst(substDict)
271 size += eSize
272}};
273
274////////////////////////////////////////////////////////////////////
275//
276// Neon (de)interlacing microops
277//
278
279let {{
280 header_output = exec_output = ''
281 for dRegs in (2, 3, 4):
282 loadConv = ''
283 unloadConv = ''
284 for dReg in range(dRegs):
285 loadConv += '''
286 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw);
287 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw);
288 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
289 unloadConv += '''
290 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]);
291 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]);
292 ''' % { "dReg" : dReg }
293 microDeintNeonCode = '''
294 const unsigned dRegs = %(dRegs)d;
295 const unsigned regs = 2 * dRegs;
296 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
297 sizeof(Element);
298 union convStruct {
299 FloatRegBits cRegs[regs];
300 Element elements[dRegs * perDReg];
301 } conv1, conv2;
302
303 %(loadConv)s
304
305 unsigned srcElem = 0;
306 for (unsigned destOffset = 0;
307 destOffset < perDReg; destOffset++) {
308 for (unsigned dReg = 0; dReg < dRegs; dReg++) {
309 conv2.elements[dReg * perDReg + destOffset] =
310 conv1.elements[srcElem++];
311 }
312 }
313
314 %(unloadConv)s
315 ''' % { "dRegs" : dRegs,
316 "loadConv" : loadConv,
317 "unloadConv" : unloadConv }
318 microDeintNeonIop = \
319 InstObjParams('deintneon%duop' % (dRegs * 2),
320 'MicroDeintNeon%dUop' % (dRegs * 2),
321 'MicroNeonMixOp',
322 { 'predicate_test': predicateTest,
323 'code' : microDeintNeonCode },
324 ['IsMicroop'])
325 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop)
326 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop)
327
328 loadConv = ''
329 unloadConv = ''
330 for dReg in range(dRegs):
331 loadConv += '''
332 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw);
333 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw);
334 ''' % { "dReg" : dReg }
335 unloadConv += '''
336 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]);
337 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]);
338 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
339 microInterNeonCode = '''
340 const unsigned dRegs = %(dRegs)d;
341 const unsigned regs = 2 * dRegs;
342 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
343 sizeof(Element);
344 union convStruct {
345 FloatRegBits cRegs[regs];
346 Element elements[dRegs * perDReg];
347 } conv1, conv2;
348
349 %(loadConv)s
350
351 unsigned destElem = 0;
352 for (unsigned srcOffset = 0;
353 srcOffset < perDReg; srcOffset++) {
354 for (unsigned dReg = 0; dReg < dRegs; dReg++) {
355 conv2.elements[destElem++] =
356 conv1.elements[dReg * perDReg + srcOffset];
357 }
358 }
359
360 %(unloadConv)s
361 ''' % { "dRegs" : dRegs,
362 "loadConv" : loadConv,
363 "unloadConv" : unloadConv }
364 microInterNeonIop = \
365 InstObjParams('interneon%duop' % (dRegs * 2),
366 'MicroInterNeon%dUop' % (dRegs * 2),
367 'MicroNeonMixOp',
368 { 'predicate_test': predicateTest,
369 'code' : microInterNeonCode },
370 ['IsMicroop'])
371 header_output += MicroNeonMixDeclare.subst(microInterNeonIop)
372 exec_output += MicroNeonMixExecute.subst(microInterNeonIop)
373}};
374
375let {{
376 exec_output = ''
377 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'):
378 for dRegs in (2, 3, 4):
379 Name = "MicroDeintNeon%dUop" % (dRegs * 2)
380 substDict = { "class_name" : Name, "targs" : type }
381 exec_output += MicroNeonExecDeclare.subst(substDict)
382 Name = "MicroInterNeon%dUop" % (dRegs * 2)
383 substDict = { "class_name" : Name, "targs" : type }
384 exec_output += MicroNeonExecDeclare.subst(substDict)
385}};
386
387////////////////////////////////////////////////////////////////////
388//
389// Neon microops to pack/unpack a single lane
390//
391
392let {{
393 header_output = exec_output = ''
394 for sRegs in 1, 2:
395 baseLoadRegs = ''
396 for reg in range(sRegs):
397 baseLoadRegs += '''
398 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw);
399 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw);
400 ''' % { "reg0" : (2 * reg + 0),
401 "reg1" : (2 * reg + 1) }
402 for dRegs in range(sRegs, 5):
403 unloadRegs = ''
404 loadRegs = baseLoadRegs
405 for reg in range(dRegs):
406 loadRegs += '''
407 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw);
408 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw);
409 ''' % { "reg" : reg }
410 unloadRegs += '''
411 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]);
412 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]);
413 ''' % { "reg" : reg }
414 microUnpackNeonCode = '''
415 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
416 sizeof(Element);
417
418 union SourceRegs {
419 FloatRegBits fRegs[2 * %(sRegs)d];
420 Element elements[%(sRegs)d * perDReg];
421 } sourceRegs;
422
423 union DestReg {
424 FloatRegBits fRegs[2];
425 Element elements[perDReg];
426 } destRegs[%(dRegs)d];
427
428 %(loadRegs)s
429
430 for (unsigned i = 0; i < %(dRegs)d; i++) {
431 destRegs[i].elements[lane] = sourceRegs.elements[i];
432 }
433
434 %(unloadRegs)s
435 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
436 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
437
438 microUnpackNeonIop = \
439 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2),
440 'MicroUnpackNeon%dto%dUop' %
441 (sRegs * 2, dRegs * 2),
442 'MicroNeonMixLaneOp',
443 { 'predicate_test': predicateTest,
444 'code' : microUnpackNeonCode },
445 ['IsMicroop'])
446 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop)
447 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop)
448
449 for sRegs in 1, 2:
450 loadRegs = ''
451 for reg in range(sRegs):
452 loadRegs += '''
453 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw);
454 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw);
455 ''' % { "reg0" : (2 * reg + 0),
456 "reg1" : (2 * reg + 1) }
457 for dRegs in range(sRegs, 5):
458 unloadRegs = ''
459 for reg in range(dRegs):
460 unloadRegs += '''
461 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]);
462 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]);
463 ''' % { "reg" : reg }
464 microUnpackAllNeonCode = '''
465 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
466 sizeof(Element);
467
468 union SourceRegs {
469 FloatRegBits fRegs[2 * %(sRegs)d];
470 Element elements[%(sRegs)d * perDReg];
471 } sourceRegs;
472
473 union DestReg {
474 FloatRegBits fRegs[2];
475 Element elements[perDReg];
476 } destRegs[%(dRegs)d];
477
478 %(loadRegs)s
479
480 for (unsigned i = 0; i < %(dRegs)d; i++) {
481 for (unsigned j = 0; j < perDReg; j++)
482 destRegs[i].elements[j] = sourceRegs.elements[i];
483 }
484
485 %(unloadRegs)s
486 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
487 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
488
489 microUnpackAllNeonIop = \
490 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2),
491 'MicroUnpackAllNeon%dto%dUop' %
492 (sRegs * 2, dRegs * 2),
493 'MicroNeonMixOp',
494 { 'predicate_test': predicateTest,
495 'code' : microUnpackAllNeonCode },
496 ['IsMicroop'])
497 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop)
498 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop)
499
500 for dRegs in 1, 2:
501 unloadRegs = ''
502 for reg in range(dRegs):
503 unloadRegs += '''
504 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]);
505 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]);
506 ''' % { "reg0" : (2 * reg + 0),
507 "reg1" : (2 * reg + 1) }
508 for sRegs in range(dRegs, 5):
509 loadRegs = ''
510 for reg in range(sRegs):
511 loadRegs += '''
512 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw);
513 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw);
514 ''' % { "reg" : reg }
515 microPackNeonCode = '''
516 const unsigned perDReg = (2 * sizeof(FloatRegBits)) /
517 sizeof(Element);
518
519 union SourceReg {
520 FloatRegBits fRegs[2];
521 Element elements[perDReg];
522 } sourceRegs[%(sRegs)d];
523
524 union DestRegs {
525 FloatRegBits fRegs[2 * %(dRegs)d];
526 Element elements[%(dRegs)d * perDReg];
527 } destRegs;
528
529 %(loadRegs)s
530
531 for (unsigned i = 0; i < %(sRegs)d; i++) {
532 destRegs.elements[i] = sourceRegs[i].elements[lane];
533 }
534
535 %(unloadRegs)s
536 ''' % { "sRegs" : sRegs, "dRegs" : dRegs,
537 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
538
539 microPackNeonIop = \
540 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2),
541 'MicroPackNeon%dto%dUop' %
542 (sRegs * 2, dRegs * 2),
543 'MicroNeonMixLaneOp',
544 { 'predicate_test': predicateTest,
545 'code' : microPackNeonCode },
546 ['IsMicroop'])
547 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop)
548 exec_output += MicroNeonMixExecute.subst(microPackNeonIop)
549}};
550
551let {{
552 exec_output = ''
553 for type in ('uint8_t', 'uint16_t', 'uint32_t'):
554 for sRegs in 1, 2:
555 for dRegs in range(sRegs, 5):
556 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop",
557 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop",
558 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"):
559 Name = format % { "sRegs" : sRegs * 2,
560 "dRegs" : dRegs * 2 }
561 substDict = { "class_name" : Name, "targs" : type }
562 exec_output += MicroNeonExecDeclare.subst(substDict)
563}};
564
565////////////////////////////////////////////////////////////////////
566//
567// Integer = Integer op Immediate microops
568//
569
570let {{
571 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop',
572 'MicroIntImmOp',
573 {'code': 'Ra = Rb + imm;',
574 'predicate_test': predicateTest},
575 ['IsMicroop'])
576
577 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
578 'MicroIntOp',
579 {'code': 'Ra = Rb + Rc;',
578 'MicroIntRegOp',
579 {'code':
580 '''Ra = Rb + shift_rm_imm(Rc, shiftAmt,
581 shiftType,
582 CondCodes<29:>);
583 ''',
580 'predicate_test': predicateTest},
581 ['IsMicroop'])
582
583 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
584 'MicroIntImmOp',
585 {'code': 'Ra = Rb - imm;',
586 'predicate_test': predicateTest},
587 ['IsMicroop'])
588
584 'predicate_test': predicateTest},
585 ['IsMicroop'])
586
587 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop',
588 'MicroIntImmOp',
589 {'code': 'Ra = Rb - imm;',
590 'predicate_test': predicateTest},
591 ['IsMicroop'])
592
593 microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop',
594 'MicroIntRegOp',
595 {'code':
596 '''Ra = Rb - shift_rm_imm(Rc, shiftAmt,
597 shiftType,
598 CondCodes<29:>);
599 ''',
600 'predicate_test': predicateTest},
601 ['IsMicroop'])
602
603 microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov',
604 'MicroIntMov',
605 {'code': 'IWRa = Rb;',
606 'predicate_test': predicateTest},
607 ['IsMicroop'])
608
589 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
590 MicroIntImmDeclare.subst(microSubiUopIop) + \
609 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
610 MicroIntImmDeclare.subst(microSubiUopIop) + \
591 MicroIntDeclare.subst(microAddUopIop)
611 MicroIntRegDeclare.subst(microAddUopIop) + \
612 MicroIntRegDeclare.subst(microSubUopIop) + \
613 MicroIntMovDeclare.subst(microUopRegMovIop)
614
592 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
593 MicroIntImmConstructor.subst(microSubiUopIop) + \
615 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
616 MicroIntImmConstructor.subst(microSubiUopIop) + \
594 MicroIntConstructor.subst(microAddUopIop)
617 MicroIntRegConstructor.subst(microAddUopIop) + \
618 MicroIntRegConstructor.subst(microSubUopIop) + \
619 MicroIntMovConstructor.subst(microUopRegMovIop)
620
595 exec_output = PredOpExecute.subst(microAddiUopIop) + \
596 PredOpExecute.subst(microSubiUopIop) + \
621 exec_output = PredOpExecute.subst(microAddiUopIop) + \
622 PredOpExecute.subst(microSubiUopIop) + \
597 PredOpExecute.subst(microAddUopIop)
623 PredOpExecute.subst(microAddUopIop) + \
624 PredOpExecute.subst(microSubUopIop) + \
625 PredOpExecute.subst(microUopRegMovIop)
598}};
599
600let {{
601 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", [])
602 header_output = MacroMemDeclare.subst(iop)
603 decoder_output = MacroMemConstructor.subst(iop)
604
605 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", [])
606 header_output += VMemMultDeclare.subst(iop)
607 decoder_output += VMemMultConstructor.subst(iop)
608
609 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", [])
610 header_output += VMemSingleDeclare.subst(iop)
611 decoder_output += VMemSingleConstructor.subst(iop)
612
613 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", [])
614 header_output += VMemMultDeclare.subst(iop)
615 decoder_output += VMemMultConstructor.subst(iop)
616
617 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", [])
618 header_output += VMemSingleDeclare.subst(iop)
619 decoder_output += VMemSingleConstructor.subst(iop)
620
621 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", [])
622 header_output += MacroVFPMemDeclare.subst(vfpIop)
623 decoder_output += MacroVFPMemConstructor.subst(vfpIop)
624}};
626}};
627
628let {{
629 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", [])
630 header_output = MacroMemDeclare.subst(iop)
631 decoder_output = MacroMemConstructor.subst(iop)
632
633 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", [])
634 header_output += VMemMultDeclare.subst(iop)
635 decoder_output += VMemMultConstructor.subst(iop)
636
637 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", [])
638 header_output += VMemSingleDeclare.subst(iop)
639 decoder_output += VMemSingleConstructor.subst(iop)
640
641 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", [])
642 header_output += VMemMultDeclare.subst(iop)
643 decoder_output += VMemMultConstructor.subst(iop)
644
645 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", [])
646 header_output += VMemSingleDeclare.subst(iop)
647 decoder_output += VMemSingleConstructor.subst(iop)
648
649 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", [])
650 header_output += MacroVFPMemDeclare.subst(vfpIop)
651 decoder_output += MacroVFPMemConstructor.subst(vfpIop)
652}};