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