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