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