data64.isa (13363:15eae7ca2bfd) data64.isa (13364:055bf0fa0f02)
1// -*- mode:c++ -*-
2
3// Copyright (c) 2011-2013, 2016-2018 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// Redistribution and use in source and binary forms, with or without
16// modification, are permitted provided that the following conditions are
17// met: redistributions of source code must retain the above copyright
18// notice, this list of conditions and the following disclaimer;
19// redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution;
22// neither the name of the copyright holders nor the names of its
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Authors: Gabe Black
39
40let {{
41
42 header_output = ""
43 decoder_output = ""
44 exec_output = ""
45
46 def createCcCode64(carry, overflow):
47 code = ""
48 code += '''
49 uint16_t _iz, _in;
50 _in = bits(resTemp, intWidth - 1);
51 _iz = ((resTemp & mask(intWidth)) == 0);
52 CondCodesNZ = (_in << 1) | _iz;
53 DPRINTF(Arm, "(in, iz) = (%d, %d)\\n", _in, _iz);
54 '''
55 if overflow and overflow != "none":
56 code += '''
57 uint16_t _iv;
58 _iv = %s & 1;
59 CondCodesV = _iv;
60 DPRINTF(Arm, "(iv) = (%%d)\\n", _iv);
61 ''' % overflow
62 if carry and carry != "none":
63 code += '''
64 uint16_t _ic;
65 _ic = %s & 1;
66 CondCodesC = _ic;
67 DPRINTF(Arm, "(ic) = (%%d)\\n", _ic);
68 ''' % carry
69 return code
70
71 oldC = 'CondCodesC'
72 oldV = 'CondCodesV'
73 # Dicts of ways to set the carry flag.
74 carryCode64 = {
75 "none": "none",
76 "add": 'findCarry(intWidth, resTemp, Op164, secOp)',
77 "sub": 'findCarry(intWidth, resTemp, Op164, ~secOp)',
78 "logic": '0'
79 }
80 # Dict of ways to set the overflow flag.
81 overflowCode64 = {
82 "none": "none",
83 "add": 'findOverflow(intWidth, resTemp, Op164, secOp)',
84 "sub": 'findOverflow(intWidth, resTemp, Op164, ~secOp)',
85 "logic": '0'
86 }
87
88 immOp2 = "uint64_t secOp M5_VAR_USED = imm;"
89 sRegOp2 = "uint64_t secOp M5_VAR_USED = " + \
90 "shiftReg64(Op264, shiftAmt, shiftType, intWidth);"
91 eRegOp2 = "uint64_t secOp M5_VAR_USED = " + \
92 "extendReg64(Op264, extendType, shiftAmt, intWidth);"
93
94 def buildDataWork(mnem, code, flagType, suffix, buildCc, buildNonCc,
95 base, templateBase):
96 code = '''
97 uint64_t resTemp M5_VAR_USED = 0;
98 ''' + code
99 ccCode = createCcCode64(carryCode64[flagType], overflowCode64[flagType])
100 Name = mnem.capitalize() + suffix
101 iop = InstObjParams(mnem, Name, base, code)
102 iopCc = InstObjParams(mnem + "s", Name + "Cc", base, code + ccCode)
103
104 def subst(iop):
105 global header_output, decoder_output, exec_output
106 header_output += eval(templateBase + "Declare").subst(iop)
107 decoder_output += eval(templateBase + "Constructor").subst(iop)
108 exec_output += BasicExecute.subst(iop)
109
110 if buildNonCc:
111 subst(iop)
112 if buildCc:
113 subst(iopCc)
114
115 def buildXImmDataInst(mnem, code, flagType = "logic", \
116 buildCc = True, buildNonCc = True, \
117 suffix = "XImm"):
118 buildDataWork(mnem, immOp2 + code, flagType, suffix,
119 buildCc, buildNonCc, "DataXImmOp", "DataXImm")
120
121 def buildXSRegDataInst(mnem, code, flagType = "logic", \
122 buildCc = True, buildNonCc = True, \
123 suffix = "XSReg"):
124 buildDataWork(mnem, sRegOp2 + code, flagType, suffix,
125 buildCc, buildNonCc, "DataXSRegOp", "DataXSReg")
126
127 def buildXERegDataInst(mnem, code, flagType = "logic", \
128 buildCc = True, buildNonCc = True, \
129 suffix = "XEReg"):
130 buildDataWork(mnem, eRegOp2 + code, flagType, suffix,
131 buildCc, buildNonCc, "DataXERegOp", "DataXEReg")
132
133 def buildDataInst(mnem, code, flagType = "logic",
134 buildCc = True, buildNonCc = True):
135 buildXImmDataInst(mnem, code, flagType, buildCc, buildNonCc)
136 buildXSRegDataInst(mnem, code, flagType, buildCc, buildNonCc)
137 buildXERegDataInst(mnem, code, flagType, buildCc, buildNonCc)
138
139 buildXImmDataInst("adr", "Dest64 = RawPC + imm", buildCc = False);
140 buildXImmDataInst("adrp", "Dest64 = (RawPC & ~mask(12)) + imm",
141 buildCc = False);
142 buildDataInst("and", "Dest64 = resTemp = Op164 & secOp;")
143 buildDataInst("eor", "Dest64 = Op164 ^ secOp;", buildCc = False)
144 buildXSRegDataInst("eon", "Dest64 = Op164 ^ ~secOp;", buildCc = False)
145 buildDataInst("sub", "Dest64 = resTemp = Op164 - secOp;", "sub")
146 buildDataInst("add", "Dest64 = resTemp = Op164 + secOp;", "add")
147 buildXSRegDataInst("adc",
148 "Dest64 = resTemp = Op164 + secOp + %s;" % oldC, "add")
149 buildXSRegDataInst("sbc",
150 "Dest64 = resTemp = Op164 - secOp - !%s;" % oldC, "sub")
151 buildDataInst("orr", "Dest64 = Op164 | secOp;", buildCc = False)
152 buildXSRegDataInst("orn", "Dest64 = Op164 | ~secOp;", buildCc = False)
153 buildXSRegDataInst("bic", "Dest64 = resTemp = Op164 & ~secOp;")
154
155 def buildDataXImmInst(mnem, code, optArgs = []):
156 global header_output, decoder_output, exec_output
157 classNamePrefix = mnem[0].upper() + mnem[1:]
158 templateBase = "DataXImm"
159 iop = InstObjParams(mnem, classNamePrefix + "64",
160 templateBase + "Op", code, optArgs)
161 header_output += eval(templateBase + "Declare").subst(iop)
162 decoder_output += eval(templateBase + "Constructor").subst(iop)
163 exec_output += BasicExecute.subst(iop)
164
165 def buildDataXRegInst(mnem, regOps, code, optArgs = [],
166 overrideOpClass=None):
167 global header_output, decoder_output, exec_output
168 templateBase = "DataX%dReg" % regOps
169 classNamePrefix = mnem[0].upper() + mnem[1:]
170 if overrideOpClass:
171 iop = InstObjParams(mnem, classNamePrefix + "64",
172 templateBase + "Op",
173 { 'code': code, 'op_class': overrideOpClass},
174 optArgs)
175 else:
176 iop = InstObjParams(mnem, classNamePrefix + "64",
177 templateBase + "Op", code, optArgs)
178 header_output += eval(templateBase + "Declare").subst(iop)
179 decoder_output += eval(templateBase + "Constructor").subst(iop)
180 exec_output += BasicExecute.subst(iop)
181
182 buildDataXRegInst("madd", 3, "Dest64 = Op164 + Op264 * Op364",
183 overrideOpClass="IntMultOp")
184 buildDataXRegInst("msub", 3, "Dest64 = Op164 - Op264 * Op364",
185 overrideOpClass="IntMultOp")
186 buildDataXRegInst("smaddl", 3,
187 "XDest = XOp1 + sext<32>(WOp2) * sext<32>(WOp3)",
188 overrideOpClass="IntMultOp")
189 buildDataXRegInst("smsubl", 3,
190 "XDest = XOp1 - sext<32>(WOp2) * sext<32>(WOp3)",
191 overrideOpClass="IntMultOp")
192 buildDataXRegInst("smulh", 2, '''
193 uint64_t op1H = (int32_t)(XOp1 >> 32);
194 uint64_t op1L = (uint32_t)XOp1;
195 uint64_t op2H = (int32_t)(XOp2 >> 32);
196 uint64_t op2L = (uint32_t)XOp2;
197 uint64_t mid1 = ((op1L * op2L) >> 32) + op1H * op2L;
198 uint64_t mid2 = op1L * op2H;
199 uint64_t result = ((uint64_t)(uint32_t)mid1 + (uint32_t)mid2) >> 32;
200 result += shiftReg64(mid1, 32, ASR, intWidth);
201 result += shiftReg64(mid2, 32, ASR, intWidth);
202 XDest = result + op1H * op2H;
203 ''', overrideOpClass="IntMultOp")
204 buildDataXRegInst("umaddl", 3, "XDest = XOp1 + WOp2 * WOp3",
205 overrideOpClass="IntMultOp")
206 buildDataXRegInst("umsubl", 3, "XDest = XOp1 - WOp2 * WOp3",
207 overrideOpClass="IntMultOp")
208 buildDataXRegInst("umulh", 2, '''
209 uint64_t op1H = (uint32_t)(XOp1 >> 32);
210 uint64_t op1L = (uint32_t)XOp1;
211 uint64_t op2H = (uint32_t)(XOp2 >> 32);
212 uint64_t op2L = (uint32_t)XOp2;
213 uint64_t mid1 = ((op1L * op2L) >> 32) + op1H * op2L;
214 uint64_t mid2 = op1L * op2H;
215 uint64_t result = ((uint64_t)(uint32_t)mid1 + (uint32_t)mid2) >> 32;
216 result += mid1 >> 32;
217 result += mid2 >> 32;
218 XDest = result + op1H * op2H;
219 ''', overrideOpClass="IntMultOp")
220
221 buildDataXRegInst("asrv", 2,
222 "Dest64 = shiftReg64(Op164, Op264, ASR, intWidth)")
223 buildDataXRegInst("lslv", 2,
224 "Dest64 = shiftReg64(Op164, Op264, LSL, intWidth)")
225 buildDataXRegInst("lsrv", 2,
226 "Dest64 = shiftReg64(Op164, Op264, LSR, intWidth)")
227 buildDataXRegInst("rorv", 2,
228 "Dest64 = shiftReg64(Op164, Op264, ROR, intWidth)")
229
230 crcCode = '''
231 constexpr uint8_t size_bytes = %(sz)d;
232 constexpr uint32_t poly = %(polynom)s;
233
234 // Initial value is often a previously evaluated
235 // crc value hence is always 32bit in CRC32
236 uint32_t initial_crc = Op164 & 0xFFFFFFFF;
237
238 uint64_t data = htole(Op264);
239 auto data_buffer = reinterpret_cast<uint8_t*>(&data);
240
241 Dest = crc32<poly>(
242 data_buffer, /* Message register */
243 initial_crc, /* Initial value of the CRC */
244 size_bytes /* Size of the original Message */
245 );
246 '''
247 buildDataXRegInst("crc32b", 2,
248 crcCode % {"sz": 1, "polynom": "0x04C11DB7"})
249 buildDataXRegInst("crc32h", 2,
250 crcCode % {"sz": 2, "polynom": "0x04C11DB7"})
251 buildDataXRegInst("crc32w", 2,
252 crcCode % {"sz": 4, "polynom": "0x04C11DB7"})
253 buildDataXRegInst("crc32x", 2,
254 crcCode % {"sz": 8, "polynom": "0x04C11DB7"})
255
256 buildDataXRegInst("crc32cb", 2,
257 crcCode % {"sz": 1, "polynom": "0x1EDC6F41"})
258 buildDataXRegInst("crc32ch", 2,
259 crcCode % {"sz": 2, "polynom": "0x1EDC6F41"})
260 buildDataXRegInst("crc32cw", 2,
261 crcCode % {"sz": 4, "polynom": "0x1EDC6F41"})
262 buildDataXRegInst("crc32cx", 2,
263 crcCode % {"sz": 8, "polynom": "0x1EDC6F41"})
264
265 buildDataXRegInst("sdiv", 2, '''
266 int64_t op1 = Op164;
267 int64_t op2 = Op264;
268 if (intWidth == 32) {
269 op1 = sext<32>(op1);
270 op2 = sext<32>(op2);
271 }
272 Dest64 = op2 == -1 ? -op1 : op2 ? op1 / op2 : 0;
273 ''', overrideOpClass="IntDivOp")
274 buildDataXRegInst("udiv", 2, "Dest64 = Op264 ? Op164 / Op264 : 0",
275 overrideOpClass="IntDivOp")
276
277 buildDataXRegInst("cls", 1, '''
278 uint64_t op1 = Op164;
279 if (bits(op1, intWidth - 1))
280 op1 ^= mask(intWidth);
281 Dest64 = (op1 == 0) ? intWidth - 1 : (intWidth - 2 - findMsbSet(op1));
282 ''')
283 buildDataXRegInst("clz", 1, '''
284 Dest64 = (Op164 == 0) ? intWidth : (intWidth - 1 - findMsbSet(Op164));
285 ''')
286 buildDataXRegInst("rbit", 1, '''
287 Dest64 = reverseBits(Op164, intWidth/8);
288 ''')
289 buildDataXRegInst("rev", 1, '''
290 if (intWidth == 32)
291 Dest64 = betole<uint32_t>(Op164);
292 else
293 Dest64 = betole<uint64_t>(Op164);
294 ''')
295 buildDataXRegInst("rev16", 1, '''
296 int count = intWidth / 16;
297 uint64_t result = 0;
298 for (unsigned i = 0; i < count; i++) {
299 uint16_t hw = Op164 >> (i * 16);
300 result |= (uint64_t)betole<uint16_t>(hw) << (i * 16);
301 }
302 Dest64 = result;
303 ''')
304 buildDataXRegInst("rev32", 1, '''
305 int count = intWidth / 32;
306 uint64_t result = 0;
307 for (unsigned i = 0; i < count; i++) {
308 uint32_t hw = Op164 >> (i * 32);
309 result |= (uint64_t)betole<uint32_t>(hw) << (i * 32);
310 }
311 Dest64 = result;
312 ''')
313
314 msrMrs64EnabledCheckCode = '''
315 // Check for read/write access right
316 if (!can%sAArch64SysReg(flat_idx, Scr64, cpsr, xc->tcBase())) {
317 if (flat_idx == MISCREG_DAIF ||
318 flat_idx == MISCREG_DC_ZVA_Xt ||
319 flat_idx == MISCREG_DC_CVAC_Xt ||
320 flat_idx == MISCREG_DC_CIVAC_Xt
321 )
322 return std::make_shared<UndefinedInstruction>(
323 machInst, 0, EC_TRAPPED_MSR_MRS_64,
324 mnemonic);
325 return std::make_shared<UndefinedInstruction>(machInst, false,
326 mnemonic);
327 }
328
1// -*- mode:c++ -*-
2
3// Copyright (c) 2011-2013, 2016-2018 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// Redistribution and use in source and binary forms, with or without
16// modification, are permitted provided that the following conditions are
17// met: redistributions of source code must retain the above copyright
18// notice, this list of conditions and the following disclaimer;
19// redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution;
22// neither the name of the copyright holders nor the names of its
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Authors: Gabe Black
39
40let {{
41
42 header_output = ""
43 decoder_output = ""
44 exec_output = ""
45
46 def createCcCode64(carry, overflow):
47 code = ""
48 code += '''
49 uint16_t _iz, _in;
50 _in = bits(resTemp, intWidth - 1);
51 _iz = ((resTemp & mask(intWidth)) == 0);
52 CondCodesNZ = (_in << 1) | _iz;
53 DPRINTF(Arm, "(in, iz) = (%d, %d)\\n", _in, _iz);
54 '''
55 if overflow and overflow != "none":
56 code += '''
57 uint16_t _iv;
58 _iv = %s & 1;
59 CondCodesV = _iv;
60 DPRINTF(Arm, "(iv) = (%%d)\\n", _iv);
61 ''' % overflow
62 if carry and carry != "none":
63 code += '''
64 uint16_t _ic;
65 _ic = %s & 1;
66 CondCodesC = _ic;
67 DPRINTF(Arm, "(ic) = (%%d)\\n", _ic);
68 ''' % carry
69 return code
70
71 oldC = 'CondCodesC'
72 oldV = 'CondCodesV'
73 # Dicts of ways to set the carry flag.
74 carryCode64 = {
75 "none": "none",
76 "add": 'findCarry(intWidth, resTemp, Op164, secOp)',
77 "sub": 'findCarry(intWidth, resTemp, Op164, ~secOp)',
78 "logic": '0'
79 }
80 # Dict of ways to set the overflow flag.
81 overflowCode64 = {
82 "none": "none",
83 "add": 'findOverflow(intWidth, resTemp, Op164, secOp)',
84 "sub": 'findOverflow(intWidth, resTemp, Op164, ~secOp)',
85 "logic": '0'
86 }
87
88 immOp2 = "uint64_t secOp M5_VAR_USED = imm;"
89 sRegOp2 = "uint64_t secOp M5_VAR_USED = " + \
90 "shiftReg64(Op264, shiftAmt, shiftType, intWidth);"
91 eRegOp2 = "uint64_t secOp M5_VAR_USED = " + \
92 "extendReg64(Op264, extendType, shiftAmt, intWidth);"
93
94 def buildDataWork(mnem, code, flagType, suffix, buildCc, buildNonCc,
95 base, templateBase):
96 code = '''
97 uint64_t resTemp M5_VAR_USED = 0;
98 ''' + code
99 ccCode = createCcCode64(carryCode64[flagType], overflowCode64[flagType])
100 Name = mnem.capitalize() + suffix
101 iop = InstObjParams(mnem, Name, base, code)
102 iopCc = InstObjParams(mnem + "s", Name + "Cc", base, code + ccCode)
103
104 def subst(iop):
105 global header_output, decoder_output, exec_output
106 header_output += eval(templateBase + "Declare").subst(iop)
107 decoder_output += eval(templateBase + "Constructor").subst(iop)
108 exec_output += BasicExecute.subst(iop)
109
110 if buildNonCc:
111 subst(iop)
112 if buildCc:
113 subst(iopCc)
114
115 def buildXImmDataInst(mnem, code, flagType = "logic", \
116 buildCc = True, buildNonCc = True, \
117 suffix = "XImm"):
118 buildDataWork(mnem, immOp2 + code, flagType, suffix,
119 buildCc, buildNonCc, "DataXImmOp", "DataXImm")
120
121 def buildXSRegDataInst(mnem, code, flagType = "logic", \
122 buildCc = True, buildNonCc = True, \
123 suffix = "XSReg"):
124 buildDataWork(mnem, sRegOp2 + code, flagType, suffix,
125 buildCc, buildNonCc, "DataXSRegOp", "DataXSReg")
126
127 def buildXERegDataInst(mnem, code, flagType = "logic", \
128 buildCc = True, buildNonCc = True, \
129 suffix = "XEReg"):
130 buildDataWork(mnem, eRegOp2 + code, flagType, suffix,
131 buildCc, buildNonCc, "DataXERegOp", "DataXEReg")
132
133 def buildDataInst(mnem, code, flagType = "logic",
134 buildCc = True, buildNonCc = True):
135 buildXImmDataInst(mnem, code, flagType, buildCc, buildNonCc)
136 buildXSRegDataInst(mnem, code, flagType, buildCc, buildNonCc)
137 buildXERegDataInst(mnem, code, flagType, buildCc, buildNonCc)
138
139 buildXImmDataInst("adr", "Dest64 = RawPC + imm", buildCc = False);
140 buildXImmDataInst("adrp", "Dest64 = (RawPC & ~mask(12)) + imm",
141 buildCc = False);
142 buildDataInst("and", "Dest64 = resTemp = Op164 & secOp;")
143 buildDataInst("eor", "Dest64 = Op164 ^ secOp;", buildCc = False)
144 buildXSRegDataInst("eon", "Dest64 = Op164 ^ ~secOp;", buildCc = False)
145 buildDataInst("sub", "Dest64 = resTemp = Op164 - secOp;", "sub")
146 buildDataInst("add", "Dest64 = resTemp = Op164 + secOp;", "add")
147 buildXSRegDataInst("adc",
148 "Dest64 = resTemp = Op164 + secOp + %s;" % oldC, "add")
149 buildXSRegDataInst("sbc",
150 "Dest64 = resTemp = Op164 - secOp - !%s;" % oldC, "sub")
151 buildDataInst("orr", "Dest64 = Op164 | secOp;", buildCc = False)
152 buildXSRegDataInst("orn", "Dest64 = Op164 | ~secOp;", buildCc = False)
153 buildXSRegDataInst("bic", "Dest64 = resTemp = Op164 & ~secOp;")
154
155 def buildDataXImmInst(mnem, code, optArgs = []):
156 global header_output, decoder_output, exec_output
157 classNamePrefix = mnem[0].upper() + mnem[1:]
158 templateBase = "DataXImm"
159 iop = InstObjParams(mnem, classNamePrefix + "64",
160 templateBase + "Op", code, optArgs)
161 header_output += eval(templateBase + "Declare").subst(iop)
162 decoder_output += eval(templateBase + "Constructor").subst(iop)
163 exec_output += BasicExecute.subst(iop)
164
165 def buildDataXRegInst(mnem, regOps, code, optArgs = [],
166 overrideOpClass=None):
167 global header_output, decoder_output, exec_output
168 templateBase = "DataX%dReg" % regOps
169 classNamePrefix = mnem[0].upper() + mnem[1:]
170 if overrideOpClass:
171 iop = InstObjParams(mnem, classNamePrefix + "64",
172 templateBase + "Op",
173 { 'code': code, 'op_class': overrideOpClass},
174 optArgs)
175 else:
176 iop = InstObjParams(mnem, classNamePrefix + "64",
177 templateBase + "Op", code, optArgs)
178 header_output += eval(templateBase + "Declare").subst(iop)
179 decoder_output += eval(templateBase + "Constructor").subst(iop)
180 exec_output += BasicExecute.subst(iop)
181
182 buildDataXRegInst("madd", 3, "Dest64 = Op164 + Op264 * Op364",
183 overrideOpClass="IntMultOp")
184 buildDataXRegInst("msub", 3, "Dest64 = Op164 - Op264 * Op364",
185 overrideOpClass="IntMultOp")
186 buildDataXRegInst("smaddl", 3,
187 "XDest = XOp1 + sext<32>(WOp2) * sext<32>(WOp3)",
188 overrideOpClass="IntMultOp")
189 buildDataXRegInst("smsubl", 3,
190 "XDest = XOp1 - sext<32>(WOp2) * sext<32>(WOp3)",
191 overrideOpClass="IntMultOp")
192 buildDataXRegInst("smulh", 2, '''
193 uint64_t op1H = (int32_t)(XOp1 >> 32);
194 uint64_t op1L = (uint32_t)XOp1;
195 uint64_t op2H = (int32_t)(XOp2 >> 32);
196 uint64_t op2L = (uint32_t)XOp2;
197 uint64_t mid1 = ((op1L * op2L) >> 32) + op1H * op2L;
198 uint64_t mid2 = op1L * op2H;
199 uint64_t result = ((uint64_t)(uint32_t)mid1 + (uint32_t)mid2) >> 32;
200 result += shiftReg64(mid1, 32, ASR, intWidth);
201 result += shiftReg64(mid2, 32, ASR, intWidth);
202 XDest = result + op1H * op2H;
203 ''', overrideOpClass="IntMultOp")
204 buildDataXRegInst("umaddl", 3, "XDest = XOp1 + WOp2 * WOp3",
205 overrideOpClass="IntMultOp")
206 buildDataXRegInst("umsubl", 3, "XDest = XOp1 - WOp2 * WOp3",
207 overrideOpClass="IntMultOp")
208 buildDataXRegInst("umulh", 2, '''
209 uint64_t op1H = (uint32_t)(XOp1 >> 32);
210 uint64_t op1L = (uint32_t)XOp1;
211 uint64_t op2H = (uint32_t)(XOp2 >> 32);
212 uint64_t op2L = (uint32_t)XOp2;
213 uint64_t mid1 = ((op1L * op2L) >> 32) + op1H * op2L;
214 uint64_t mid2 = op1L * op2H;
215 uint64_t result = ((uint64_t)(uint32_t)mid1 + (uint32_t)mid2) >> 32;
216 result += mid1 >> 32;
217 result += mid2 >> 32;
218 XDest = result + op1H * op2H;
219 ''', overrideOpClass="IntMultOp")
220
221 buildDataXRegInst("asrv", 2,
222 "Dest64 = shiftReg64(Op164, Op264, ASR, intWidth)")
223 buildDataXRegInst("lslv", 2,
224 "Dest64 = shiftReg64(Op164, Op264, LSL, intWidth)")
225 buildDataXRegInst("lsrv", 2,
226 "Dest64 = shiftReg64(Op164, Op264, LSR, intWidth)")
227 buildDataXRegInst("rorv", 2,
228 "Dest64 = shiftReg64(Op164, Op264, ROR, intWidth)")
229
230 crcCode = '''
231 constexpr uint8_t size_bytes = %(sz)d;
232 constexpr uint32_t poly = %(polynom)s;
233
234 // Initial value is often a previously evaluated
235 // crc value hence is always 32bit in CRC32
236 uint32_t initial_crc = Op164 & 0xFFFFFFFF;
237
238 uint64_t data = htole(Op264);
239 auto data_buffer = reinterpret_cast<uint8_t*>(&data);
240
241 Dest = crc32<poly>(
242 data_buffer, /* Message register */
243 initial_crc, /* Initial value of the CRC */
244 size_bytes /* Size of the original Message */
245 );
246 '''
247 buildDataXRegInst("crc32b", 2,
248 crcCode % {"sz": 1, "polynom": "0x04C11DB7"})
249 buildDataXRegInst("crc32h", 2,
250 crcCode % {"sz": 2, "polynom": "0x04C11DB7"})
251 buildDataXRegInst("crc32w", 2,
252 crcCode % {"sz": 4, "polynom": "0x04C11DB7"})
253 buildDataXRegInst("crc32x", 2,
254 crcCode % {"sz": 8, "polynom": "0x04C11DB7"})
255
256 buildDataXRegInst("crc32cb", 2,
257 crcCode % {"sz": 1, "polynom": "0x1EDC6F41"})
258 buildDataXRegInst("crc32ch", 2,
259 crcCode % {"sz": 2, "polynom": "0x1EDC6F41"})
260 buildDataXRegInst("crc32cw", 2,
261 crcCode % {"sz": 4, "polynom": "0x1EDC6F41"})
262 buildDataXRegInst("crc32cx", 2,
263 crcCode % {"sz": 8, "polynom": "0x1EDC6F41"})
264
265 buildDataXRegInst("sdiv", 2, '''
266 int64_t op1 = Op164;
267 int64_t op2 = Op264;
268 if (intWidth == 32) {
269 op1 = sext<32>(op1);
270 op2 = sext<32>(op2);
271 }
272 Dest64 = op2 == -1 ? -op1 : op2 ? op1 / op2 : 0;
273 ''', overrideOpClass="IntDivOp")
274 buildDataXRegInst("udiv", 2, "Dest64 = Op264 ? Op164 / Op264 : 0",
275 overrideOpClass="IntDivOp")
276
277 buildDataXRegInst("cls", 1, '''
278 uint64_t op1 = Op164;
279 if (bits(op1, intWidth - 1))
280 op1 ^= mask(intWidth);
281 Dest64 = (op1 == 0) ? intWidth - 1 : (intWidth - 2 - findMsbSet(op1));
282 ''')
283 buildDataXRegInst("clz", 1, '''
284 Dest64 = (Op164 == 0) ? intWidth : (intWidth - 1 - findMsbSet(Op164));
285 ''')
286 buildDataXRegInst("rbit", 1, '''
287 Dest64 = reverseBits(Op164, intWidth/8);
288 ''')
289 buildDataXRegInst("rev", 1, '''
290 if (intWidth == 32)
291 Dest64 = betole<uint32_t>(Op164);
292 else
293 Dest64 = betole<uint64_t>(Op164);
294 ''')
295 buildDataXRegInst("rev16", 1, '''
296 int count = intWidth / 16;
297 uint64_t result = 0;
298 for (unsigned i = 0; i < count; i++) {
299 uint16_t hw = Op164 >> (i * 16);
300 result |= (uint64_t)betole<uint16_t>(hw) << (i * 16);
301 }
302 Dest64 = result;
303 ''')
304 buildDataXRegInst("rev32", 1, '''
305 int count = intWidth / 32;
306 uint64_t result = 0;
307 for (unsigned i = 0; i < count; i++) {
308 uint32_t hw = Op164 >> (i * 32);
309 result |= (uint64_t)betole<uint32_t>(hw) << (i * 32);
310 }
311 Dest64 = result;
312 ''')
313
314 msrMrs64EnabledCheckCode = '''
315 // Check for read/write access right
316 if (!can%sAArch64SysReg(flat_idx, Scr64, cpsr, xc->tcBase())) {
317 if (flat_idx == MISCREG_DAIF ||
318 flat_idx == MISCREG_DC_ZVA_Xt ||
319 flat_idx == MISCREG_DC_CVAC_Xt ||
320 flat_idx == MISCREG_DC_CIVAC_Xt
321 )
322 return std::make_shared<UndefinedInstruction>(
323 machInst, 0, EC_TRAPPED_MSR_MRS_64,
324 mnemonic);
325 return std::make_shared<UndefinedInstruction>(machInst, false,
326 mnemonic);
327 }
328
329 // Check for traps to supervisor (FP/SIMD regs)
330 if (el <= EL1 && msrMrs64TrapToSup(flat_idx, el, Cpacr64))
331 return std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
332 EC_TRAPPED_SIMD_FP);
333
334 bool is_vfp_neon = false;
335
336 // Check for traps to hypervisor
337 if ((ArmSystem::haveVirtualization(xc->tcBase()) && el <= EL2) &&
338 msrMrs64TrapToHyp(flat_idx, el, %s, CptrEl264, Hcr64,
339 Scr64, cpsr, &is_vfp_neon)) {
340
341 return std::make_shared<HypervisorTrap>(
342 machInst, is_vfp_neon ? 0x1E00000 : imm,
343 is_vfp_neon ? EC_TRAPPED_SIMD_FP : EC_TRAPPED_MSR_MRS_64);
344 }
345
346 // Check for traps to secure monitor
347 if ((ArmSystem::haveSecurity(xc->tcBase()) && el <= EL3) &&
348 msrMrs64TrapToMon(flat_idx, CptrEl364, el, &is_vfp_neon)) {
349 return std::make_shared<SecureMonitorTrap>(
350 machInst,
351 is_vfp_neon ? 0x1E00000 : imm,
352 is_vfp_neon ? EC_TRAPPED_SIMD_FP : EC_TRAPPED_MSR_MRS_64);
353 }
329 fault = this->trap(xc->tcBase(), flat_idx, el, imm);
330 if (fault != NoFault) return fault;
354 '''
355
356 mrsCode = '''
357 MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->
358 flattenRegId(RegId(MiscRegClass, op1)).index();
359 CPSR cpsr = Cpsr;
360 ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
361 %s
362 XDest = MiscOp1_ud;
331 '''
332
333 mrsCode = '''
334 MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->
335 flattenRegId(RegId(MiscRegClass, op1)).index();
336 CPSR cpsr = Cpsr;
337 ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
338 %s
339 XDest = MiscOp1_ud;
363 ''' % (msrMrs64EnabledCheckCode % ('Read', 'true'),)
340 ''' % (msrMrs64EnabledCheckCode % ('Read'),)
364
365 mrsIop = InstObjParams("mrs", "Mrs64", "RegMiscRegImmOp64",
366 mrsCode,
367 ["IsSerializeBefore"])
368 header_output += RegMiscRegOp64Declare.subst(mrsIop)
369 decoder_output += RegMiscRegOp64Constructor.subst(mrsIop)
370 exec_output += BasicExecute.subst(mrsIop)
371
372 buildDataXRegInst("mrsNZCV", 1, '''
373 CPSR cpsr = 0;
374 cpsr.nz = CondCodesNZ;
375 cpsr.c = CondCodesC;
376 cpsr.v = CondCodesV;
377 XDest = cpsr;
378 ''')
379
380 msrCode = '''
381 MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->
382 flattenRegId(RegId(MiscRegClass, dest)).index();
383 CPSR cpsr = Cpsr;
384 ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
385 %s
386 MiscDest_ud = XOp1;
341
342 mrsIop = InstObjParams("mrs", "Mrs64", "RegMiscRegImmOp64",
343 mrsCode,
344 ["IsSerializeBefore"])
345 header_output += RegMiscRegOp64Declare.subst(mrsIop)
346 decoder_output += RegMiscRegOp64Constructor.subst(mrsIop)
347 exec_output += BasicExecute.subst(mrsIop)
348
349 buildDataXRegInst("mrsNZCV", 1, '''
350 CPSR cpsr = 0;
351 cpsr.nz = CondCodesNZ;
352 cpsr.c = CondCodesC;
353 cpsr.v = CondCodesV;
354 XDest = cpsr;
355 ''')
356
357 msrCode = '''
358 MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->
359 flattenRegId(RegId(MiscRegClass, dest)).index();
360 CPSR cpsr = Cpsr;
361 ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
362 %s
363 MiscDest_ud = XOp1;
387 ''' % (msrMrs64EnabledCheckCode % ('Write', 'false'),)
364 ''' % (msrMrs64EnabledCheckCode % ('Write'),)
388
389 msrIop = InstObjParams("msr", "Msr64", "MiscRegRegImmOp64",
390 msrCode,
391 ["IsSerializeAfter", "IsNonSpeculative"])
392 header_output += MiscRegRegOp64Declare.subst(msrIop)
393 decoder_output += MiscRegRegOp64Constructor.subst(msrIop)
394 exec_output += BasicExecute.subst(msrIop)
395
396
397 buildDataXRegInst("msrNZCV", 1, '''
398 CPSR cpsr = XOp1;
399 CondCodesNZ = cpsr.nz;
400 CondCodesC = cpsr.c;
401 CondCodesV = cpsr.v;
402 ''')
403
404 msr_check_code = '''
405 MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->
406 flattenRegId(RegId(MiscRegClass, dest)).index();
407 CPSR cpsr = Cpsr;
408 ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
409 %s
365
366 msrIop = InstObjParams("msr", "Msr64", "MiscRegRegImmOp64",
367 msrCode,
368 ["IsSerializeAfter", "IsNonSpeculative"])
369 header_output += MiscRegRegOp64Declare.subst(msrIop)
370 decoder_output += MiscRegRegOp64Constructor.subst(msrIop)
371 exec_output += BasicExecute.subst(msrIop)
372
373
374 buildDataXRegInst("msrNZCV", 1, '''
375 CPSR cpsr = XOp1;
376 CondCodesNZ = cpsr.nz;
377 CondCodesC = cpsr.c;
378 CondCodesV = cpsr.v;
379 ''')
380
381 msr_check_code = '''
382 MiscRegIndex flat_idx = (MiscRegIndex) xc->tcBase()->
383 flattenRegId(RegId(MiscRegClass, dest)).index();
384 CPSR cpsr = Cpsr;
385 ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
386 %s
410 ''' % (msrMrs64EnabledCheckCode % ('Write', 'false'),)
387 ''' % (msrMrs64EnabledCheckCode % ('Write'),)
411
412
413 msrdczva_ea_code = msr_check_code
414 msrdczva_ea_code += '''
415 Request::Flags memAccessFlags = Request::CACHE_BLOCK_ZERO |
416 ArmISA::TLB::MustBeOne;
417 EA = XBase;
418 assert(!(Dczid & 0x10));
419 uint64_t op_size = power(2, Dczid + 2);
420 EA &= ~(op_size - 1);
421
422 '''
423
424 msrDCZVAIop = InstObjParams("dc zva", "Dczva", "SysDC64",
425 { "ea_code" : msrdczva_ea_code,
426 "memacc_code" : ';',
427 "use_uops" : 0,
428 "op_wb" : ";",
429 "fa_code" : ";"},
430 ['IsStore', 'IsMemRef']);
431 header_output += DCStore64Declare.subst(msrDCZVAIop);
432 decoder_output += DCStore64Constructor.subst(msrDCZVAIop);
433 exec_output += DCStore64Execute.subst(msrDCZVAIop);
434 exec_output += DCStore64InitiateAcc.subst(msrDCZVAIop);
435 exec_output += Store64CompleteAcc.subst(msrDCZVAIop);
436
437
438 msrdccvau_ea_code = msr_check_code
439 msrdccvau_ea_code += '''
440 Request::Flags memAccessFlags = Request::CLEAN | Request::DST_POU |
441 ArmISA::TLB::MustBeOne;
442 EA = XBase;
443 System *sys = xc->tcBase()->getSystemPtr();
444 Addr op_size = sys->cacheLineSize();
445 EA &= ~(op_size - 1);
446 '''
447
448 msrDCCVAUIop = InstObjParams("dc cvau", "Dccvau", "SysDC64",
449 { "ea_code" : msrdccvau_ea_code,
450 "memacc_code" : ';',
451 "use_uops" : 0,
452 "op_wb" : ";", "fa_code" : ";"},
453 ['IsStore', 'IsMemRef']);
454 header_output += DCStore64Declare.subst(msrDCCVAUIop);
455 decoder_output += DCStore64Constructor.subst(msrDCCVAUIop);
456 exec_output += DCStore64Execute.subst(msrDCCVAUIop);
457 exec_output += DCStore64InitiateAcc.subst(msrDCCVAUIop);
458 exec_output += Store64CompleteAcc.subst(msrDCCVAUIop);
459
460
461 msrdccvac_ea_code = msr_check_code
462 msrdccvac_ea_code += '''
463 Request::Flags memAccessFlags = Request::CLEAN | Request::DST_POC |
464 ArmISA::TLB::MustBeOne;
465 EA = XBase;
466 System *sys = xc->tcBase()->getSystemPtr();
467 Addr op_size = sys->cacheLineSize();
468 EA &= ~(op_size - 1);
469 '''
470
471 msrDCCVACIop = InstObjParams("dc cvac", "Dccvac", "SysDC64",
472 { "ea_code" : msrdccvac_ea_code,
473 "memacc_code" : ';',
474 "use_uops" : 0,
475 "op_wb" : ";", "fa_code" : ";"},
476 ['IsStore', 'IsMemRef']);
477 header_output += DCStore64Declare.subst(msrDCCVACIop);
478 decoder_output += DCStore64Constructor.subst(msrDCCVACIop);
479 exec_output += DCStore64Execute.subst(msrDCCVACIop);
480 exec_output += DCStore64InitiateAcc.subst(msrDCCVACIop);
481 exec_output += Store64CompleteAcc.subst(msrDCCVACIop);
482
483
484 msrdccivac_ea_code = msr_check_code
485 msrdccivac_ea_code += '''
486 Request::Flags memAccessFlags = Request::CLEAN |
487 Request::INVALIDATE | Request::DST_POC | ArmISA::TLB::MustBeOne;
488 EA = XBase;
489 System *sys = xc->tcBase()->getSystemPtr();
490 Addr op_size = sys->cacheLineSize();
491 EA &= ~(op_size - 1);
492 '''
493
494 msrDCCIVACIop = InstObjParams("dc civac", "Dccivac", "SysDC64",
495 { "ea_code" : msrdccivac_ea_code,
496 "memacc_code" : ';',
497 "use_uops" : 0,
498 "op_wb" : ";", "fa_code" : ";"},
499 ['IsStore', 'IsMemRef']);
500 header_output += DCStore64Declare.subst(msrDCCIVACIop);
501 decoder_output += DCStore64Constructor.subst(msrDCCIVACIop);
502 exec_output += DCStore64Execute.subst(msrDCCIVACIop);
503 exec_output += DCStore64InitiateAcc.subst(msrDCCIVACIop);
504 exec_output += Store64CompleteAcc.subst(msrDCCIVACIop);
505
506
507 msrdcivac_ea_code = msr_check_code
508 msrdcivac_ea_code += '''
509 Request::Flags memAccessFlags = Request::INVALIDATE |
510 Request::DST_POC | ArmISA::TLB::MustBeOne;
511 EA = XBase;
512 HCR hcr = Hcr64;
513 SCR scr = Scr64;
514 if (el == EL1 && ArmSystem::haveVirtualization(xc->tcBase()) &&
515 hcr.vm && (scr.ns || !ArmSystem::haveSecurity(xc->tcBase()))) {
516 memAccessFlags = memAccessFlags | Request::CLEAN;
517 }
518 System *sys = xc->tcBase()->getSystemPtr();
519 Addr op_size = sys->cacheLineSize();
520 EA &= ~(op_size - 1);
521 '''
522
523 msrDCIVACIop = InstObjParams("dc ivac", "Dcivac", "SysDC64",
524 { "ea_code" : msrdcivac_ea_code,
525 "memacc_code" : ';',
526 "use_uops" : 0,
527 "op_wb" : ";", "fa_code" : ";"},
528 ['IsStore', 'IsMemRef']);
529 header_output += DCStore64Declare.subst(msrDCIVACIop);
530 decoder_output += DCStore64Constructor.subst(msrDCIVACIop);
531 exec_output += DCStore64Execute.subst(msrDCIVACIop);
532 exec_output += DCStore64InitiateAcc.subst(msrDCIVACIop);
533 exec_output += Store64CompleteAcc.subst(msrDCIVACIop);
534
535
536 buildDataXImmInst("msrSP", '''
537 if (!canWriteAArch64SysReg(
538 (MiscRegIndex) xc->tcBase()->flattenRegId(
539 RegId(MiscRegClass, dest)).index(),
540 Scr64, Cpsr, xc->tcBase())) {
541 return std::make_shared<UndefinedInstruction>(machInst, false,
542 mnemonic);
543 }
544 MiscDest_ud = imm;
545 ''', optArgs = ["IsSerializeAfter", "IsNonSpeculative"])
546
547 buildDataXImmInst("msrDAIFSet", '''
548 if (!canWriteAArch64SysReg(
549 (MiscRegIndex) xc->tcBase()->flattenRegId(
550 RegId(MiscRegClass, dest)).index(),
551 Scr64, Cpsr, xc->tcBase())) {
552 return std::make_shared<UndefinedInstruction>(
553 machInst, 0, EC_TRAPPED_MSR_MRS_64,
554 mnemonic);
555 }
556 CPSR cpsr = Cpsr;
557 cpsr.daif = cpsr.daif | imm;
558 Cpsr = cpsr;
559 ''', optArgs = ["IsSerializeAfter", "IsNonSpeculative"])
560
561 buildDataXImmInst("msrDAIFClr", '''
562 if (!canWriteAArch64SysReg(
563 (MiscRegIndex) xc->tcBase()->flattenRegId(
564 RegId(MiscRegClass, dest)).index(),
565 Scr64, Cpsr, xc->tcBase())) {
566 return std::make_shared<UndefinedInstruction>(
567 machInst, 0, EC_TRAPPED_MSR_MRS_64,
568 mnemonic);
569 }
570 CPSR cpsr = Cpsr;
571 cpsr.daif = cpsr.daif & ~imm;
572 Cpsr = cpsr;
573 ''', optArgs = ["IsSerializeAfter", "IsNonSpeculative"])
574
575 def buildDataXCompInst(mnem, instType, suffix, code):
576 global header_output, decoder_output, exec_output
577 templateBase = "DataXCond%s" % instType
578 iop = InstObjParams(mnem, mnem.capitalize() + suffix + "64",
579 templateBase + "Op", code)
580 header_output += eval(templateBase + "Declare").subst(iop)
581 decoder_output += eval(templateBase + "Constructor").subst(iop)
582 exec_output += BasicExecute.subst(iop)
583
584 def buildDataXCondImmInst(mnem, code):
585 buildDataXCompInst(mnem, "CompImm", "Imm", code)
586 def buildDataXCondRegInst(mnem, code):
587 buildDataXCompInst(mnem, "CompReg", "Reg", code)
588 def buildDataXCondSelInst(mnem, code):
589 buildDataXCompInst(mnem, "Sel", "", code)
590
591 def condCompCode(flagType, op, imm):
592 ccCode = createCcCode64(carryCode64[flagType], overflowCode64[flagType])
593 opDecl = "uint64_t secOp M5_VAR_USED = imm;"
594 if not imm:
595 opDecl = "uint64_t secOp M5_VAR_USED = Op264;"
596 return opDecl + '''
597 if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode)) {
598 uint64_t resTemp = Op164 ''' + op + ''' secOp;
599 ''' + ccCode + '''
600 } else {
601 CondCodesNZ = (defCc >> 2) & 0x3;
602 CondCodesC = (defCc >> 1) & 0x1;
603 CondCodesV = defCc & 0x1;
604 }
605 '''
606
607 buildDataXCondImmInst("ccmn", condCompCode("add", "+", True))
608 buildDataXCondImmInst("ccmp", condCompCode("sub", "-", True))
609 buildDataXCondRegInst("ccmn", condCompCode("add", "+", False))
610 buildDataXCondRegInst("ccmp", condCompCode("sub", "-", False))
611
612 condSelCode = '''
613 if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode)) {
614 Dest64 = Op164;
615 } else {
616 Dest64 = %(altVal)s;
617 }
618 '''
619 buildDataXCondSelInst("csel", condSelCode % {"altVal" : "Op264"})
620 buildDataXCondSelInst("csinc", condSelCode % {"altVal" : "Op264 + 1"})
621 buildDataXCondSelInst("csinv", condSelCode % {"altVal" : "~Op264"})
622 buildDataXCondSelInst("csneg", condSelCode % {"altVal" : "-Op264"})
623}};
388
389
390 msrdczva_ea_code = msr_check_code
391 msrdczva_ea_code += '''
392 Request::Flags memAccessFlags = Request::CACHE_BLOCK_ZERO |
393 ArmISA::TLB::MustBeOne;
394 EA = XBase;
395 assert(!(Dczid & 0x10));
396 uint64_t op_size = power(2, Dczid + 2);
397 EA &= ~(op_size - 1);
398
399 '''
400
401 msrDCZVAIop = InstObjParams("dc zva", "Dczva", "SysDC64",
402 { "ea_code" : msrdczva_ea_code,
403 "memacc_code" : ';',
404 "use_uops" : 0,
405 "op_wb" : ";",
406 "fa_code" : ";"},
407 ['IsStore', 'IsMemRef']);
408 header_output += DCStore64Declare.subst(msrDCZVAIop);
409 decoder_output += DCStore64Constructor.subst(msrDCZVAIop);
410 exec_output += DCStore64Execute.subst(msrDCZVAIop);
411 exec_output += DCStore64InitiateAcc.subst(msrDCZVAIop);
412 exec_output += Store64CompleteAcc.subst(msrDCZVAIop);
413
414
415 msrdccvau_ea_code = msr_check_code
416 msrdccvau_ea_code += '''
417 Request::Flags memAccessFlags = Request::CLEAN | Request::DST_POU |
418 ArmISA::TLB::MustBeOne;
419 EA = XBase;
420 System *sys = xc->tcBase()->getSystemPtr();
421 Addr op_size = sys->cacheLineSize();
422 EA &= ~(op_size - 1);
423 '''
424
425 msrDCCVAUIop = InstObjParams("dc cvau", "Dccvau", "SysDC64",
426 { "ea_code" : msrdccvau_ea_code,
427 "memacc_code" : ';',
428 "use_uops" : 0,
429 "op_wb" : ";", "fa_code" : ";"},
430 ['IsStore', 'IsMemRef']);
431 header_output += DCStore64Declare.subst(msrDCCVAUIop);
432 decoder_output += DCStore64Constructor.subst(msrDCCVAUIop);
433 exec_output += DCStore64Execute.subst(msrDCCVAUIop);
434 exec_output += DCStore64InitiateAcc.subst(msrDCCVAUIop);
435 exec_output += Store64CompleteAcc.subst(msrDCCVAUIop);
436
437
438 msrdccvac_ea_code = msr_check_code
439 msrdccvac_ea_code += '''
440 Request::Flags memAccessFlags = Request::CLEAN | Request::DST_POC |
441 ArmISA::TLB::MustBeOne;
442 EA = XBase;
443 System *sys = xc->tcBase()->getSystemPtr();
444 Addr op_size = sys->cacheLineSize();
445 EA &= ~(op_size - 1);
446 '''
447
448 msrDCCVACIop = InstObjParams("dc cvac", "Dccvac", "SysDC64",
449 { "ea_code" : msrdccvac_ea_code,
450 "memacc_code" : ';',
451 "use_uops" : 0,
452 "op_wb" : ";", "fa_code" : ";"},
453 ['IsStore', 'IsMemRef']);
454 header_output += DCStore64Declare.subst(msrDCCVACIop);
455 decoder_output += DCStore64Constructor.subst(msrDCCVACIop);
456 exec_output += DCStore64Execute.subst(msrDCCVACIop);
457 exec_output += DCStore64InitiateAcc.subst(msrDCCVACIop);
458 exec_output += Store64CompleteAcc.subst(msrDCCVACIop);
459
460
461 msrdccivac_ea_code = msr_check_code
462 msrdccivac_ea_code += '''
463 Request::Flags memAccessFlags = Request::CLEAN |
464 Request::INVALIDATE | Request::DST_POC | ArmISA::TLB::MustBeOne;
465 EA = XBase;
466 System *sys = xc->tcBase()->getSystemPtr();
467 Addr op_size = sys->cacheLineSize();
468 EA &= ~(op_size - 1);
469 '''
470
471 msrDCCIVACIop = InstObjParams("dc civac", "Dccivac", "SysDC64",
472 { "ea_code" : msrdccivac_ea_code,
473 "memacc_code" : ';',
474 "use_uops" : 0,
475 "op_wb" : ";", "fa_code" : ";"},
476 ['IsStore', 'IsMemRef']);
477 header_output += DCStore64Declare.subst(msrDCCIVACIop);
478 decoder_output += DCStore64Constructor.subst(msrDCCIVACIop);
479 exec_output += DCStore64Execute.subst(msrDCCIVACIop);
480 exec_output += DCStore64InitiateAcc.subst(msrDCCIVACIop);
481 exec_output += Store64CompleteAcc.subst(msrDCCIVACIop);
482
483
484 msrdcivac_ea_code = msr_check_code
485 msrdcivac_ea_code += '''
486 Request::Flags memAccessFlags = Request::INVALIDATE |
487 Request::DST_POC | ArmISA::TLB::MustBeOne;
488 EA = XBase;
489 HCR hcr = Hcr64;
490 SCR scr = Scr64;
491 if (el == EL1 && ArmSystem::haveVirtualization(xc->tcBase()) &&
492 hcr.vm && (scr.ns || !ArmSystem::haveSecurity(xc->tcBase()))) {
493 memAccessFlags = memAccessFlags | Request::CLEAN;
494 }
495 System *sys = xc->tcBase()->getSystemPtr();
496 Addr op_size = sys->cacheLineSize();
497 EA &= ~(op_size - 1);
498 '''
499
500 msrDCIVACIop = InstObjParams("dc ivac", "Dcivac", "SysDC64",
501 { "ea_code" : msrdcivac_ea_code,
502 "memacc_code" : ';',
503 "use_uops" : 0,
504 "op_wb" : ";", "fa_code" : ";"},
505 ['IsStore', 'IsMemRef']);
506 header_output += DCStore64Declare.subst(msrDCIVACIop);
507 decoder_output += DCStore64Constructor.subst(msrDCIVACIop);
508 exec_output += DCStore64Execute.subst(msrDCIVACIop);
509 exec_output += DCStore64InitiateAcc.subst(msrDCIVACIop);
510 exec_output += Store64CompleteAcc.subst(msrDCIVACIop);
511
512
513 buildDataXImmInst("msrSP", '''
514 if (!canWriteAArch64SysReg(
515 (MiscRegIndex) xc->tcBase()->flattenRegId(
516 RegId(MiscRegClass, dest)).index(),
517 Scr64, Cpsr, xc->tcBase())) {
518 return std::make_shared<UndefinedInstruction>(machInst, false,
519 mnemonic);
520 }
521 MiscDest_ud = imm;
522 ''', optArgs = ["IsSerializeAfter", "IsNonSpeculative"])
523
524 buildDataXImmInst("msrDAIFSet", '''
525 if (!canWriteAArch64SysReg(
526 (MiscRegIndex) xc->tcBase()->flattenRegId(
527 RegId(MiscRegClass, dest)).index(),
528 Scr64, Cpsr, xc->tcBase())) {
529 return std::make_shared<UndefinedInstruction>(
530 machInst, 0, EC_TRAPPED_MSR_MRS_64,
531 mnemonic);
532 }
533 CPSR cpsr = Cpsr;
534 cpsr.daif = cpsr.daif | imm;
535 Cpsr = cpsr;
536 ''', optArgs = ["IsSerializeAfter", "IsNonSpeculative"])
537
538 buildDataXImmInst("msrDAIFClr", '''
539 if (!canWriteAArch64SysReg(
540 (MiscRegIndex) xc->tcBase()->flattenRegId(
541 RegId(MiscRegClass, dest)).index(),
542 Scr64, Cpsr, xc->tcBase())) {
543 return std::make_shared<UndefinedInstruction>(
544 machInst, 0, EC_TRAPPED_MSR_MRS_64,
545 mnemonic);
546 }
547 CPSR cpsr = Cpsr;
548 cpsr.daif = cpsr.daif & ~imm;
549 Cpsr = cpsr;
550 ''', optArgs = ["IsSerializeAfter", "IsNonSpeculative"])
551
552 def buildDataXCompInst(mnem, instType, suffix, code):
553 global header_output, decoder_output, exec_output
554 templateBase = "DataXCond%s" % instType
555 iop = InstObjParams(mnem, mnem.capitalize() + suffix + "64",
556 templateBase + "Op", code)
557 header_output += eval(templateBase + "Declare").subst(iop)
558 decoder_output += eval(templateBase + "Constructor").subst(iop)
559 exec_output += BasicExecute.subst(iop)
560
561 def buildDataXCondImmInst(mnem, code):
562 buildDataXCompInst(mnem, "CompImm", "Imm", code)
563 def buildDataXCondRegInst(mnem, code):
564 buildDataXCompInst(mnem, "CompReg", "Reg", code)
565 def buildDataXCondSelInst(mnem, code):
566 buildDataXCompInst(mnem, "Sel", "", code)
567
568 def condCompCode(flagType, op, imm):
569 ccCode = createCcCode64(carryCode64[flagType], overflowCode64[flagType])
570 opDecl = "uint64_t secOp M5_VAR_USED = imm;"
571 if not imm:
572 opDecl = "uint64_t secOp M5_VAR_USED = Op264;"
573 return opDecl + '''
574 if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode)) {
575 uint64_t resTemp = Op164 ''' + op + ''' secOp;
576 ''' + ccCode + '''
577 } else {
578 CondCodesNZ = (defCc >> 2) & 0x3;
579 CondCodesC = (defCc >> 1) & 0x1;
580 CondCodesV = defCc & 0x1;
581 }
582 '''
583
584 buildDataXCondImmInst("ccmn", condCompCode("add", "+", True))
585 buildDataXCondImmInst("ccmp", condCompCode("sub", "-", True))
586 buildDataXCondRegInst("ccmn", condCompCode("add", "+", False))
587 buildDataXCondRegInst("ccmp", condCompCode("sub", "-", False))
588
589 condSelCode = '''
590 if (testPredicate(CondCodesNZ, CondCodesC, CondCodesV, condCode)) {
591 Dest64 = Op164;
592 } else {
593 Dest64 = %(altVal)s;
594 }
595 '''
596 buildDataXCondSelInst("csel", condSelCode % {"altVal" : "Op264"})
597 buildDataXCondSelInst("csinc", condSelCode % {"altVal" : "Op264 + 1"})
598 buildDataXCondSelInst("csinv", condSelCode % {"altVal" : "~Op264"})
599 buildDataXCondSelInst("csneg", condSelCode % {"altVal" : "-Op264"})
600}};