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