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