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