1// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
| 1// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
|
| 2// Copyright (c) 2015 Advanced Micro Devices, Inc.
|
2// All rights reserved. 3// 4// The license below extends only to copyright in the software and shall 5// not be construed as granting a license to any other intellectual 6// property including but not limited to intellectual property relating 7// to a hardware implementation of the functionality of the software 8// licensed hereunder. You may use the software subject to the license 9// terms below provided that you ensure that this notice is replicated 10// unmodified and in its entirety in all distributions of the software, 11// modified or unmodified, in source code or in binary form. 12// 13// Copyright (c) 2008 The Regents of The University of Michigan 14// All rights reserved. 15// 16// Redistribution and use in source and binary forms, with or without 17// modification, are permitted provided that the following conditions are 18// met: redistributions of source code must retain the above copyright 19// notice, this list of conditions and the following disclaimer; 20// redistributions in binary form must reproduce the above copyright 21// notice, this list of conditions and the following disclaimer in the 22// documentation and/or other materials provided with the distribution; 23// neither the name of the copyright holders nor the names of its 24// contributors may be used to endorse or promote products derived from 25// this software without specific prior written permission. 26// 27// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38// 39// Authors: Gabe Black 40 41////////////////////////////////////////////////////////////////////////// 42// 43// LdStOp Microop templates 44// 45////////////////////////////////////////////////////////////////////////// 46 47// LEA template 48 49def template MicroLeaExecute {{ 50 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 51 Trace::InstRecord *traceData) const 52 { 53 Fault fault = NoFault; 54 Addr EA; 55 56 %(op_decl)s; 57 %(op_rd)s; 58 %(ea_code)s; 59 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 60 61 %(code)s; 62 if(fault == NoFault) 63 { 64 %(op_wb)s; 65 } 66 67 return fault; 68 } 69}}; 70 71def template MicroLeaDeclare {{ 72 class %(class_name)s : public %(base_class)s 73 { 74 public: 75 %(class_name)s(ExtMachInst _machInst, 76 const char * instMnem, uint64_t setFlags, 77 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 78 uint64_t _disp, InstRegIndex _segment, 79 InstRegIndex _data, 80 uint8_t _dataSize, uint8_t _addressSize, 81 Request::FlagsType _memFlags); 82 83 %(BasicExecDeclare)s 84 }; 85}}; 86 87// Load templates 88 89def template MicroLoadExecute {{ 90 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 91 Trace::InstRecord *traceData) const 92 { 93 Fault fault = NoFault; 94 Addr EA; 95 96 %(op_decl)s; 97 %(op_rd)s; 98 %(ea_code)s; 99 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 100
| 3// All rights reserved. 4// 5// The license below extends only to copyright in the software and shall 6// not be construed as granting a license to any other intellectual 7// property including but not limited to intellectual property relating 8// to a hardware implementation of the functionality of the software 9// licensed hereunder. You may use the software subject to the license 10// terms below provided that you ensure that this notice is replicated 11// unmodified and in its entirety in all distributions of the software, 12// modified or unmodified, in source code or in binary form. 13// 14// Copyright (c) 2008 The Regents of The University of Michigan 15// All rights reserved. 16// 17// Redistribution and use in source and binary forms, with or without 18// modification, are permitted provided that the following conditions are 19// met: redistributions of source code must retain the above copyright 20// notice, this list of conditions and the following disclaimer; 21// redistributions in binary form must reproduce the above copyright 22// notice, this list of conditions and the following disclaimer in the 23// documentation and/or other materials provided with the distribution; 24// neither the name of the copyright holders nor the names of its 25// contributors may be used to endorse or promote products derived from 26// this software without specific prior written permission. 27// 28// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39// 40// Authors: Gabe Black 41 42////////////////////////////////////////////////////////////////////////// 43// 44// LdStOp Microop templates 45// 46////////////////////////////////////////////////////////////////////////// 47 48// LEA template 49 50def template MicroLeaExecute {{ 51 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 52 Trace::InstRecord *traceData) const 53 { 54 Fault fault = NoFault; 55 Addr EA; 56 57 %(op_decl)s; 58 %(op_rd)s; 59 %(ea_code)s; 60 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 61 62 %(code)s; 63 if(fault == NoFault) 64 { 65 %(op_wb)s; 66 } 67 68 return fault; 69 } 70}}; 71 72def template MicroLeaDeclare {{ 73 class %(class_name)s : public %(base_class)s 74 { 75 public: 76 %(class_name)s(ExtMachInst _machInst, 77 const char * instMnem, uint64_t setFlags, 78 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 79 uint64_t _disp, InstRegIndex _segment, 80 InstRegIndex _data, 81 uint8_t _dataSize, uint8_t _addressSize, 82 Request::FlagsType _memFlags); 83 84 %(BasicExecDeclare)s 85 }; 86}}; 87 88// Load templates 89 90def template MicroLoadExecute {{ 91 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 92 Trace::InstRecord *traceData) const 93 { 94 Fault fault = NoFault; 95 Addr EA; 96 97 %(op_decl)s; 98 %(op_rd)s; 99 %(ea_code)s; 100 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 101
|
101 fault = readMemAtomic(xc, traceData, EA, Mem, dataSize, memFlags);
| 102 fault = readMemAtomic(xc, traceData, EA, Mem, 103 %(memDataSize)s, memFlags);
|
102 103 if (fault == NoFault) { 104 %(code)s; 105 } else if (memFlags & Request::PREFETCH) { 106 // For prefetches, ignore any faults/exceptions. 107 return NoFault; 108 } 109 if(fault == NoFault) 110 { 111 %(op_wb)s; 112 } 113 114 return fault; 115 } 116}}; 117 118def template MicroLoadInitiateAcc {{ 119 Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc, 120 Trace::InstRecord * traceData) const 121 { 122 Fault fault = NoFault; 123 Addr EA; 124 125 %(op_decl)s; 126 %(op_rd)s; 127 %(ea_code)s; 128 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 129
| 104 105 if (fault == NoFault) { 106 %(code)s; 107 } else if (memFlags & Request::PREFETCH) { 108 // For prefetches, ignore any faults/exceptions. 109 return NoFault; 110 } 111 if(fault == NoFault) 112 { 113 %(op_wb)s; 114 } 115 116 return fault; 117 } 118}}; 119 120def template MicroLoadInitiateAcc {{ 121 Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc, 122 Trace::InstRecord * traceData) const 123 { 124 Fault fault = NoFault; 125 Addr EA; 126 127 %(op_decl)s; 128 %(op_rd)s; 129 %(ea_code)s; 130 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 131
|
130 fault = initiateMemRead(xc, traceData, EA, dataSize, memFlags);
| 132 fault = initiateMemRead(xc, traceData, EA, 133 %(memDataSize)s, memFlags);
|
131 132 return fault; 133 } 134}}; 135 136def template MicroLoadCompleteAcc {{ 137 Fault %(class_name)s::completeAcc(PacketPtr pkt, 138 CPU_EXEC_CONTEXT * xc, 139 Trace::InstRecord * traceData) const 140 { 141 Fault fault = NoFault; 142 143 %(op_decl)s; 144 %(op_rd)s; 145
| 134 135 return fault; 136 } 137}}; 138 139def template MicroLoadCompleteAcc {{ 140 Fault %(class_name)s::completeAcc(PacketPtr pkt, 141 CPU_EXEC_CONTEXT * xc, 142 Trace::InstRecord * traceData) const 143 { 144 Fault fault = NoFault; 145 146 %(op_decl)s; 147 %(op_rd)s; 148
|
146 getMem(pkt, Mem, dataSize, traceData);
| 149 getMem(pkt, Mem, %(memDataSize)s, traceData);
|
147 148 %(code)s; 149 150 if(fault == NoFault) 151 { 152 %(op_wb)s; 153 } 154 155 return fault; 156 } 157}}; 158 159// Store templates 160 161def template MicroStoreExecute {{ 162 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT * xc, 163 Trace::InstRecord *traceData) const 164 { 165 Fault fault = NoFault; 166 167 Addr EA; 168 %(op_decl)s; 169 %(op_rd)s; 170 %(ea_code)s; 171 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 172 173 %(code)s; 174 175 if(fault == NoFault) 176 {
| 150 151 %(code)s; 152 153 if(fault == NoFault) 154 { 155 %(op_wb)s; 156 } 157 158 return fault; 159 } 160}}; 161 162// Store templates 163 164def template MicroStoreExecute {{ 165 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT * xc, 166 Trace::InstRecord *traceData) const 167 { 168 Fault fault = NoFault; 169 170 Addr EA; 171 %(op_decl)s; 172 %(op_rd)s; 173 %(ea_code)s; 174 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 175 176 %(code)s; 177 178 if(fault == NoFault) 179 {
|
177 fault = writeMemAtomic(xc, traceData, Mem, dataSize, EA,
| 180 fault = writeMemAtomic(xc, traceData, Mem, %(memDataSize)s, EA,
|
178 memFlags, NULL); 179 if(fault == NoFault) 180 { 181 %(op_wb)s; 182 } 183 } 184 185 return fault; 186 } 187}}; 188 189def template MicroStoreInitiateAcc {{ 190 Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc, 191 Trace::InstRecord * traceData) const 192 { 193 Fault fault = NoFault; 194 195 Addr EA; 196 %(op_decl)s; 197 %(op_rd)s; 198 %(ea_code)s; 199 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 200 201 %(code)s; 202 203 if(fault == NoFault) 204 {
| 181 memFlags, NULL); 182 if(fault == NoFault) 183 { 184 %(op_wb)s; 185 } 186 } 187 188 return fault; 189 } 190}}; 191 192def template MicroStoreInitiateAcc {{ 193 Fault %(class_name)s::initiateAcc(CPU_EXEC_CONTEXT * xc, 194 Trace::InstRecord * traceData) const 195 { 196 Fault fault = NoFault; 197 198 Addr EA; 199 %(op_decl)s; 200 %(op_rd)s; 201 %(ea_code)s; 202 DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA); 203 204 %(code)s; 205 206 if(fault == NoFault) 207 {
|
205 fault = writeMemTiming(xc, traceData, Mem, dataSize, EA,
| 208 fault = writeMemTiming(xc, traceData, Mem, %(memDataSize)s, EA,
|
206 memFlags, NULL); 207 } 208 return fault; 209 } 210}}; 211 212def template MicroStoreCompleteAcc {{ 213 Fault %(class_name)s::completeAcc(PacketPtr pkt, 214 CPU_EXEC_CONTEXT * xc, Trace::InstRecord * traceData) const 215 { 216 %(op_decl)s; 217 %(op_rd)s; 218 %(complete_code)s; 219 %(op_wb)s; 220 return NoFault; 221 } 222}}; 223 224// Common templates 225 226//This delcares the initiateAcc function in memory operations 227def template InitiateAccDeclare {{ 228 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 229}}; 230 231//This declares the completeAcc function in memory operations 232def template CompleteAccDeclare {{ 233 Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; 234}}; 235 236def template MicroLdStOpDeclare {{ 237 class %(class_name)s : public %(base_class)s 238 { 239 public: 240 %(class_name)s(ExtMachInst _machInst, 241 const char * instMnem, uint64_t setFlags, 242 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 243 uint64_t _disp, InstRegIndex _segment, 244 InstRegIndex _data, 245 uint8_t _dataSize, uint8_t _addressSize, 246 Request::FlagsType _memFlags); 247 248 %(BasicExecDeclare)s 249 250 %(InitiateAccDeclare)s 251 252 %(CompleteAccDeclare)s 253 }; 254}}; 255
| 209 memFlags, NULL); 210 } 211 return fault; 212 } 213}}; 214 215def template MicroStoreCompleteAcc {{ 216 Fault %(class_name)s::completeAcc(PacketPtr pkt, 217 CPU_EXEC_CONTEXT * xc, Trace::InstRecord * traceData) const 218 { 219 %(op_decl)s; 220 %(op_rd)s; 221 %(complete_code)s; 222 %(op_wb)s; 223 return NoFault; 224 } 225}}; 226 227// Common templates 228 229//This delcares the initiateAcc function in memory operations 230def template InitiateAccDeclare {{ 231 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 232}}; 233 234//This declares the completeAcc function in memory operations 235def template CompleteAccDeclare {{ 236 Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; 237}}; 238 239def template MicroLdStOpDeclare {{ 240 class %(class_name)s : public %(base_class)s 241 { 242 public: 243 %(class_name)s(ExtMachInst _machInst, 244 const char * instMnem, uint64_t setFlags, 245 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 246 uint64_t _disp, InstRegIndex _segment, 247 InstRegIndex _data, 248 uint8_t _dataSize, uint8_t _addressSize, 249 Request::FlagsType _memFlags); 250 251 %(BasicExecDeclare)s 252 253 %(InitiateAccDeclare)s 254 255 %(CompleteAccDeclare)s 256 }; 257}}; 258
|
| 259// LdStSplitOp is a load or store that uses a pair of regs as the 260// source or destination. Used for cmpxchg{8,16}b. 261def template MicroLdStSplitOpDeclare {{ 262 class %(class_name)s : public %(base_class)s 263 { 264 public: 265 %(class_name)s(ExtMachInst _machInst, 266 const char * instMnem, uint64_t setFlags, 267 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 268 uint64_t _disp, InstRegIndex _segment, 269 InstRegIndex _dataLow, InstRegIndex _dataHi, 270 uint8_t _dataSize, uint8_t _addressSize, 271 Request::FlagsType _memFlags); 272 273 %(BasicExecDeclare)s 274 275 %(InitiateAccDeclare)s 276 277 %(CompleteAccDeclare)s 278 }; 279}}; 280
|
256def template MicroLdStOpConstructor {{ 257 %(class_name)s::%(class_name)s( 258 ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 259 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 260 uint64_t _disp, InstRegIndex _segment, 261 InstRegIndex _data, 262 uint8_t _dataSize, uint8_t _addressSize, 263 Request::FlagsType _memFlags) : 264 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 265 _scale, _index, _base, 266 _disp, _segment, _data, 267 _dataSize, _addressSize, _memFlags, %(op_class)s) 268 { 269 %(constructor)s; 270 } 271}}; 272
| 281def template MicroLdStOpConstructor {{ 282 %(class_name)s::%(class_name)s( 283 ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 284 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 285 uint64_t _disp, InstRegIndex _segment, 286 InstRegIndex _data, 287 uint8_t _dataSize, uint8_t _addressSize, 288 Request::FlagsType _memFlags) : 289 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 290 _scale, _index, _base, 291 _disp, _segment, _data, 292 _dataSize, _addressSize, _memFlags, %(op_class)s) 293 { 294 %(constructor)s; 295 } 296}}; 297
|
| 298def template MicroLdStSplitOpConstructor {{ 299 %(class_name)s::%(class_name)s( 300 ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 301 uint8_t _scale, InstRegIndex _index, InstRegIndex _base, 302 uint64_t _disp, InstRegIndex _segment, 303 InstRegIndex _dataLow, InstRegIndex _dataHi, 304 uint8_t _dataSize, uint8_t _addressSize, 305 Request::FlagsType _memFlags) : 306 %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 307 _scale, _index, _base, 308 _disp, _segment, _dataLow, _dataHi, 309 _dataSize, _addressSize, _memFlags, %(op_class)s) 310 { 311 %(constructor)s; 312 } 313}}; 314
|
273let {{ 274 class LdStOp(X86Microop): 275 def __init__(self, data, segment, addr, disp, 276 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec): 277 self.data = data 278 [self.scale, self.index, self.base] = addr 279 self.disp = disp 280 self.segment = segment 281 self.dataSize = dataSize 282 self.addressSize = addressSize 283 self.memFlags = baseFlags 284 if atCPL0: 285 self.memFlags += " | (CPL0FlagBit << FlagShift)" 286 self.instFlags = "" 287 if prefetch: 288 self.memFlags += " | Request::PREFETCH" 289 self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)" 290 if nonSpec: 291 self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)" 292 self.memFlags += " | (machInst.legacy.addr ? " + \ 293 "(AddrSizeFlagBit << FlagShift) : 0)" 294 295 def getAllocator(self, microFlags): 296 allocator = '''new %(class_name)s(machInst, macrocodeBlock, 297 %(flags)s, %(scale)s, %(index)s, %(base)s, 298 %(disp)s, %(segment)s, %(data)s, 299 %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % { 300 "class_name" : self.className, 301 "flags" : self.microFlagsText(microFlags) + self.instFlags, 302 "scale" : self.scale, "index" : self.index, 303 "base" : self.base, 304 "disp" : self.disp, 305 "segment" : self.segment, "data" : self.data, 306 "dataSize" : self.dataSize, "addressSize" : self.addressSize, 307 "memFlags" : self.memFlags} 308 return allocator 309 310 class BigLdStOp(X86Microop): 311 def __init__(self, data, segment, addr, disp, 312 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec): 313 self.data = data 314 [self.scale, self.index, self.base] = addr 315 self.disp = disp 316 self.segment = segment 317 self.dataSize = dataSize 318 self.addressSize = addressSize 319 self.memFlags = baseFlags 320 if atCPL0: 321 self.memFlags += " | (CPL0FlagBit << FlagShift)" 322 self.instFlags = "" 323 if prefetch: 324 self.memFlags += " | Request::PREFETCH" 325 self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)" 326 if nonSpec: 327 self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)" 328 self.memFlags += " | (machInst.legacy.addr ? " + \ 329 "(AddrSizeFlagBit << FlagShift) : 0)" 330 331 def getAllocator(self, microFlags): 332 allocString = ''' 333 (%(dataSize)s >= 4) ? 334 (StaticInstPtr)(new %(class_name)sBig(machInst, 335 macrocodeBlock, %(flags)s, %(scale)s, %(index)s, 336 %(base)s, %(disp)s, %(segment)s, %(data)s, 337 %(dataSize)s, %(addressSize)s, %(memFlags)s)) : 338 (StaticInstPtr)(new %(class_name)s(machInst, 339 macrocodeBlock, %(flags)s, %(scale)s, %(index)s, 340 %(base)s, %(disp)s, %(segment)s, %(data)s, 341 %(dataSize)s, %(addressSize)s, %(memFlags)s)) 342 ''' 343 allocator = allocString % { 344 "class_name" : self.className, 345 "flags" : self.microFlagsText(microFlags) + self.instFlags, 346 "scale" : self.scale, "index" : self.index, 347 "base" : self.base, 348 "disp" : self.disp, 349 "segment" : self.segment, "data" : self.data, 350 "dataSize" : self.dataSize, "addressSize" : self.addressSize, 351 "memFlags" : self.memFlags} 352 return allocator
| 315let {{ 316 class LdStOp(X86Microop): 317 def __init__(self, data, segment, addr, disp, 318 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec): 319 self.data = data 320 [self.scale, self.index, self.base] = addr 321 self.disp = disp 322 self.segment = segment 323 self.dataSize = dataSize 324 self.addressSize = addressSize 325 self.memFlags = baseFlags 326 if atCPL0: 327 self.memFlags += " | (CPL0FlagBit << FlagShift)" 328 self.instFlags = "" 329 if prefetch: 330 self.memFlags += " | Request::PREFETCH" 331 self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)" 332 if nonSpec: 333 self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)" 334 self.memFlags += " | (machInst.legacy.addr ? " + \ 335 "(AddrSizeFlagBit << FlagShift) : 0)" 336 337 def getAllocator(self, microFlags): 338 allocator = '''new %(class_name)s(machInst, macrocodeBlock, 339 %(flags)s, %(scale)s, %(index)s, %(base)s, 340 %(disp)s, %(segment)s, %(data)s, 341 %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % { 342 "class_name" : self.className, 343 "flags" : self.microFlagsText(microFlags) + self.instFlags, 344 "scale" : self.scale, "index" : self.index, 345 "base" : self.base, 346 "disp" : self.disp, 347 "segment" : self.segment, "data" : self.data, 348 "dataSize" : self.dataSize, "addressSize" : self.addressSize, 349 "memFlags" : self.memFlags} 350 return allocator 351 352 class BigLdStOp(X86Microop): 353 def __init__(self, data, segment, addr, disp, 354 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec): 355 self.data = data 356 [self.scale, self.index, self.base] = addr 357 self.disp = disp 358 self.segment = segment 359 self.dataSize = dataSize 360 self.addressSize = addressSize 361 self.memFlags = baseFlags 362 if atCPL0: 363 self.memFlags += " | (CPL0FlagBit << FlagShift)" 364 self.instFlags = "" 365 if prefetch: 366 self.memFlags += " | Request::PREFETCH" 367 self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)" 368 if nonSpec: 369 self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)" 370 self.memFlags += " | (machInst.legacy.addr ? " + \ 371 "(AddrSizeFlagBit << FlagShift) : 0)" 372 373 def getAllocator(self, microFlags): 374 allocString = ''' 375 (%(dataSize)s >= 4) ? 376 (StaticInstPtr)(new %(class_name)sBig(machInst, 377 macrocodeBlock, %(flags)s, %(scale)s, %(index)s, 378 %(base)s, %(disp)s, %(segment)s, %(data)s, 379 %(dataSize)s, %(addressSize)s, %(memFlags)s)) : 380 (StaticInstPtr)(new %(class_name)s(machInst, 381 macrocodeBlock, %(flags)s, %(scale)s, %(index)s, 382 %(base)s, %(disp)s, %(segment)s, %(data)s, 383 %(dataSize)s, %(addressSize)s, %(memFlags)s)) 384 ''' 385 allocator = allocString % { 386 "class_name" : self.className, 387 "flags" : self.microFlagsText(microFlags) + self.instFlags, 388 "scale" : self.scale, "index" : self.index, 389 "base" : self.base, 390 "disp" : self.disp, 391 "segment" : self.segment, "data" : self.data, 392 "dataSize" : self.dataSize, "addressSize" : self.addressSize, 393 "memFlags" : self.memFlags} 394 return allocator
|
| 395 396 class LdStSplitOp(LdStOp): 397 def __init__(self, data, segment, addr, disp, 398 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec): 399 super(LdStSplitOp, self).__init__(0, segment, addr, disp, 400 dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec) 401 (self.dataLow, self.dataHi) = data 402 403 def getAllocator(self, microFlags): 404 allocString = '''(StaticInstPtr)(new %(class_name)s(machInst, 405 macrocodeBlock, %(flags)s, %(scale)s, %(index)s, 406 %(base)s, %(disp)s, %(segment)s, 407 %(dataLow)s, %(dataHi)s, 408 %(dataSize)s, %(addressSize)s, %(memFlags)s)) 409 ''' 410 allocator = allocString % { 411 "class_name" : self.className, 412 "flags" : self.microFlagsText(microFlags) + self.instFlags, 413 "scale" : self.scale, "index" : self.index, 414 "base" : self.base, 415 "disp" : self.disp, 416 "segment" : self.segment, 417 "dataLow" : self.dataLow, "dataHi" : self.dataHi, 418 "dataSize" : self.dataSize, "addressSize" : self.addressSize, 419 "memFlags" : self.memFlags} 420 return allocator 421
|
353}}; 354 355let {{ 356 357 # Make these empty strings so that concatenating onto 358 # them will always work. 359 header_output = "" 360 decoder_output = "" 361 exec_output = "" 362
| 422}}; 423 424let {{ 425 426 # Make these empty strings so that concatenating onto 427 # them will always work. 428 header_output = "" 429 decoder_output = "" 430 exec_output = "" 431
|
363 calculateEA = ''' 364 EA = SegBase + bits(scale * Index + Base + disp, addressSize * 8 - 1, 0); 365 '''
| 432 segmentEAExpr = \ 433 'bits(scale * Index + Base + disp, addressSize * 8 - 1, 0);'
|
366
| 434
|
| 435 calculateEA = 'EA = SegBase + ' + segmentEAExpr 436
|
367 def defineMicroLoadOp(mnemonic, code, bigCode='',
| 437 def defineMicroLoadOp(mnemonic, code, bigCode='',
|
368 mem_flags="0", big=True):
| 438 mem_flags="0", big=True, nonSpec=False):
|
369 global header_output 370 global decoder_output 371 global exec_output 372 global microopClasses 373 Name = mnemonic 374 name = mnemonic.lower() 375 376 # Build up the all register version of this micro op 377 iops = [InstObjParams(name, Name, 'X86ISA::LdStOp',
| 439 global header_output 440 global decoder_output 441 global exec_output 442 global microopClasses 443 Name = mnemonic 444 name = mnemonic.lower() 445 446 # Build up the all register version of this micro op 447 iops = [InstObjParams(name, Name, 'X86ISA::LdStOp',
|
378 {"code": code, "ea_code": calculateEA})]
| 448 { "code": code, 449 "ea_code": calculateEA, 450 "memDataSize": "dataSize" })]
|
379 if big: 380 iops += [InstObjParams(name, Name + "Big", 'X86ISA::LdStOp',
| 451 if big: 452 iops += [InstObjParams(name, Name + "Big", 'X86ISA::LdStOp',
|
381 {"code": bigCode, "ea_code": calculateEA})]
| 453 { "code": bigCode, 454 "ea_code": calculateEA, 455 "memDataSize": "dataSize" })]
|
382 for iop in iops: 383 header_output += MicroLdStOpDeclare.subst(iop) 384 decoder_output += MicroLdStOpConstructor.subst(iop) 385 exec_output += MicroLoadExecute.subst(iop) 386 exec_output += MicroLoadInitiateAcc.subst(iop) 387 exec_output += MicroLoadCompleteAcc.subst(iop) 388 389 base = LdStOp 390 if big: 391 base = BigLdStOp 392 class LoadOp(base): 393 def __init__(self, data, segment, addr, disp = 0, 394 dataSize="env.dataSize", 395 addressSize="env.addressSize",
| 456 for iop in iops: 457 header_output += MicroLdStOpDeclare.subst(iop) 458 decoder_output += MicroLdStOpConstructor.subst(iop) 459 exec_output += MicroLoadExecute.subst(iop) 460 exec_output += MicroLoadInitiateAcc.subst(iop) 461 exec_output += MicroLoadCompleteAcc.subst(iop) 462 463 base = LdStOp 464 if big: 465 base = BigLdStOp 466 class LoadOp(base): 467 def __init__(self, data, segment, addr, disp = 0, 468 dataSize="env.dataSize", 469 addressSize="env.addressSize",
|
396 atCPL0=False, prefetch=False, nonSpec=False):
| 470 atCPL0=False, prefetch=False, nonSpec=nonSpec):
|
397 super(LoadOp, self).__init__(data, segment, addr, 398 disp, dataSize, addressSize, mem_flags, 399 atCPL0, prefetch, nonSpec) 400 self.className = Name 401 self.mnemonic = name 402 403 microopClasses[name] = LoadOp 404 405 defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);', 406 'Data = Mem & mask(dataSize * 8);') 407 defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 408 'Data = Mem & mask(dataSize * 8);', 409 '(StoreCheck << FlagShift)') 410 defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);', 411 'Data = Mem & mask(dataSize * 8);',
| 471 super(LoadOp, self).__init__(data, segment, addr, 472 disp, dataSize, addressSize, mem_flags, 473 atCPL0, prefetch, nonSpec) 474 self.className = Name 475 self.mnemonic = name 476 477 microopClasses[name] = LoadOp 478 479 defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);', 480 'Data = Mem & mask(dataSize * 8);') 481 defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 482 'Data = Mem & mask(dataSize * 8);', 483 '(StoreCheck << FlagShift)') 484 defineMicroLoadOp('Ldstl', 'Data = merge(Data, Mem, dataSize);', 485 'Data = Mem & mask(dataSize * 8);',
|
412 '(StoreCheck << FlagShift) | Request::LOCKED_RMW')
| 486 '(StoreCheck << FlagShift) | Request::LOCKED_RMW', 487 nonSpec=True)
|
413 414 defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False) 415 416 defineMicroLoadOp('Ldfp87', code=''' 417 switch (dataSize) 418 { 419 case 4: 420 FpData_df = *(float *)&Mem; 421 break; 422 case 8: 423 FpData_df = *(double *)&Mem; 424 break; 425 default: 426 panic("Unhandled data size in LdFp87.\\n"); 427 } 428 ''', big = False) 429 430 # Load integer from memory into x87 top-of-stack register. 431 # Used to implement fild instruction. 432 defineMicroLoadOp('Ldifp87', code=''' 433 switch (dataSize) 434 { 435 case 2: 436 FpData_df = (int64_t)sext<16>(Mem); 437 break; 438 case 4: 439 FpData_df = (int64_t)sext<32>(Mem); 440 break; 441 case 8: 442 FpData_df = (int64_t)Mem; 443 break; 444 default: 445 panic("Unhandled data size in LdIFp87.\\n"); 446 } 447 ''', big = False) 448
| 488 489 defineMicroLoadOp('Ldfp', code='FpData_uqw = Mem', big = False) 490 491 defineMicroLoadOp('Ldfp87', code=''' 492 switch (dataSize) 493 { 494 case 4: 495 FpData_df = *(float *)&Mem; 496 break; 497 case 8: 498 FpData_df = *(double *)&Mem; 499 break; 500 default: 501 panic("Unhandled data size in LdFp87.\\n"); 502 } 503 ''', big = False) 504 505 # Load integer from memory into x87 top-of-stack register. 506 # Used to implement fild instruction. 507 defineMicroLoadOp('Ldifp87', code=''' 508 switch (dataSize) 509 { 510 case 2: 511 FpData_df = (int64_t)sext<16>(Mem); 512 break; 513 case 4: 514 FpData_df = (int64_t)sext<32>(Mem); 515 break; 516 case 8: 517 FpData_df = (int64_t)Mem; 518 break; 519 default: 520 panic("Unhandled data size in LdIFp87.\\n"); 521 } 522 ''', big = False) 523
|
| 524 def defineMicroLoadSplitOp(mnemonic, code, mem_flags="0", nonSpec=False): 525 global header_output 526 global decoder_output 527 global exec_output 528 global microopClasses 529 Name = mnemonic 530 name = mnemonic.lower() 531 532 iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp', 533 { "code": code, 534 "ea_code": calculateEA, 535 "memDataSize": "2 * dataSize" }) 536 537 header_output += MicroLdStSplitOpDeclare.subst(iop) 538 decoder_output += MicroLdStSplitOpConstructor.subst(iop) 539 exec_output += MicroLoadExecute.subst(iop) 540 exec_output += MicroLoadInitiateAcc.subst(iop) 541 exec_output += MicroLoadCompleteAcc.subst(iop) 542 543 class LoadOp(LdStSplitOp): 544 def __init__(self, data, segment, addr, disp = 0, 545 dataSize="env.dataSize", 546 addressSize="env.addressSize", 547 atCPL0=False, prefetch=False, nonSpec=nonSpec): 548 super(LoadOp, self).__init__(data, segment, addr, 549 disp, dataSize, addressSize, mem_flags, 550 atCPL0, prefetch, nonSpec) 551 self.className = Name 552 self.mnemonic = name 553 554 microopClasses[name] = LoadOp 555 556 code = ''' 557 switch (dataSize) { 558 case 4: 559 DataLow = bits(Mem_u2qw[0], 31, 0); 560 DataHi = bits(Mem_u2qw[0], 63, 32); 561 break; 562 case 8: 563 DataLow = Mem_u2qw[0]; 564 DataHi = Mem_u2qw[1]; 565 break; 566 default: 567 panic("Unhandled data size %d in LdSplit.\\n", dataSize); 568 }''' 569 570 defineMicroLoadSplitOp('LdSplit', code, 571 '(StoreCheck << FlagShift)') 572 573 defineMicroLoadSplitOp('LdSplitl', code, 574 '(StoreCheck << FlagShift) | Request::LOCKED_RMW', 575 nonSpec=True) 576
|
449 def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"): 450 global header_output 451 global decoder_output 452 global exec_output 453 global microopClasses 454 Name = mnemonic 455 name = mnemonic.lower() 456 457 # Build up the all register version of this micro op 458 iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
| 577 def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"): 578 global header_output 579 global decoder_output 580 global exec_output 581 global microopClasses 582 Name = mnemonic 583 name = mnemonic.lower() 584 585 # Build up the all register version of this micro op 586 iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
|
459 {"code": code, 460 "complete_code": completeCode, 461 "ea_code": calculateEA})
| 587 { "code": code, 588 "complete_code": completeCode, 589 "ea_code": calculateEA, 590 "memDataSize": "dataSize" })
|
462 header_output += MicroLdStOpDeclare.subst(iop) 463 decoder_output += MicroLdStOpConstructor.subst(iop) 464 exec_output += MicroStoreExecute.subst(iop) 465 exec_output += MicroStoreInitiateAcc.subst(iop) 466 exec_output += MicroStoreCompleteAcc.subst(iop) 467 468 class StoreOp(LdStOp): 469 def __init__(self, data, segment, addr, disp = 0, 470 dataSize="env.dataSize", 471 addressSize="env.addressSize", 472 atCPL0=False, nonSpec=False): 473 super(StoreOp, self).__init__(data, segment, addr, disp, 474 dataSize, addressSize, mem_flags, atCPL0, False, 475 nonSpec) 476 self.className = Name 477 self.mnemonic = name 478 479 microopClasses[name] = StoreOp 480 481 defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);') 482 defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);', 483 mem_flags="Request::LOCKED_RMW") 484 485 defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;') 486 487 defineMicroStoreOp('Stfp87', code=''' 488 switch (dataSize) 489 { 490 case 4: { 491 float single(FpData_df); 492 Mem = *(uint32_t *)&single; 493 } break; 494 case 8: 495 Mem = *(uint64_t *)&FpData_df; 496 break; 497 default: 498 panic("Unhandled data size in StFp87.\\n"); 499 } 500 ''') 501 502 defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS") 503
| 591 header_output += MicroLdStOpDeclare.subst(iop) 592 decoder_output += MicroLdStOpConstructor.subst(iop) 593 exec_output += MicroStoreExecute.subst(iop) 594 exec_output += MicroStoreInitiateAcc.subst(iop) 595 exec_output += MicroStoreCompleteAcc.subst(iop) 596 597 class StoreOp(LdStOp): 598 def __init__(self, data, segment, addr, disp = 0, 599 dataSize="env.dataSize", 600 addressSize="env.addressSize", 601 atCPL0=False, nonSpec=False): 602 super(StoreOp, self).__init__(data, segment, addr, disp, 603 dataSize, addressSize, mem_flags, atCPL0, False, 604 nonSpec) 605 self.className = Name 606 self.mnemonic = name 607 608 microopClasses[name] = StoreOp 609 610 defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);') 611 defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);', 612 mem_flags="Request::LOCKED_RMW") 613 614 defineMicroStoreOp('Stfp', code='Mem = FpData_uqw;') 615 616 defineMicroStoreOp('Stfp87', code=''' 617 switch (dataSize) 618 { 619 case 4: { 620 float single(FpData_df); 621 Mem = *(uint32_t *)&single; 622 } break; 623 case 8: 624 Mem = *(uint64_t *)&FpData_df; 625 break; 626 default: 627 panic("Unhandled data size in StFp87.\\n"); 628 } 629 ''') 630 631 defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS") 632
|
| 633 def defineMicroStoreSplitOp(mnemonic, code, 634 completeCode="", mem_flags="0"): 635 global header_output 636 global decoder_output 637 global exec_output 638 global microopClasses 639 Name = mnemonic 640 name = mnemonic.lower() 641 642 iop = InstObjParams(name, Name, 'X86ISA::LdStSplitOp', 643 { "code": code, 644 "complete_code": completeCode, 645 "ea_code": calculateEA, 646 "memDataSize": "2 * dataSize" }) 647 648 header_output += MicroLdStSplitOpDeclare.subst(iop) 649 decoder_output += MicroLdStSplitOpConstructor.subst(iop) 650 exec_output += MicroStoreExecute.subst(iop) 651 exec_output += MicroStoreInitiateAcc.subst(iop) 652 exec_output += MicroStoreCompleteAcc.subst(iop) 653 654 class StoreOp(LdStSplitOp): 655 def __init__(self, data, segment, addr, disp = 0, 656 dataSize="env.dataSize", 657 addressSize="env.addressSize", 658 atCPL0=False, nonSpec=False): 659 super(StoreOp, self).__init__(data, segment, addr, disp, 660 dataSize, addressSize, mem_flags, atCPL0, False, 661 nonSpec) 662 self.className = Name 663 self.mnemonic = name 664 665 microopClasses[name] = StoreOp 666 667 code = ''' 668 switch (dataSize) { 669 case 4: 670 Mem_u2qw[0] = (DataHi << 32) | DataLow; 671 break; 672 case 8: 673 Mem_u2qw[0] = DataLow; 674 Mem_u2qw[1] = DataHi; 675 break; 676 default: 677 panic("Unhandled data size %d in StSplit.\\n", dataSize); 678 }''' 679 680 defineMicroStoreSplitOp('StSplit', code); 681 682 defineMicroStoreSplitOp('StSplitul', code, 683 mem_flags='Request::LOCKED_RMW') 684
|
504 iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
| 685 iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
|
505 {"code": "Data = merge(Data, EA, dataSize);", 506 "ea_code": ''' 507 EA = bits(scale * Index + Base + disp, addressSize * 8 - 1, 0); 508 '''})
| 686 { "code": "Data = merge(Data, EA, dataSize);", 687 "ea_code": "EA = " + segmentEAExpr, 688 "memDataSize": "dataSize" })
|
509 header_output += MicroLeaDeclare.subst(iop) 510 decoder_output += MicroLdStOpConstructor.subst(iop) 511 exec_output += MicroLeaExecute.subst(iop) 512 513 class LeaOp(LdStOp): 514 def __init__(self, data, segment, addr, disp = 0, 515 dataSize="env.dataSize", addressSize="env.addressSize"): 516 super(LeaOp, self).__init__(data, segment, addr, disp, 517 dataSize, addressSize, "0", False, False, False) 518 self.className = "Lea" 519 self.mnemonic = "lea" 520 521 microopClasses["lea"] = LeaOp 522 523 524 iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
| 689 header_output += MicroLeaDeclare.subst(iop) 690 decoder_output += MicroLdStOpConstructor.subst(iop) 691 exec_output += MicroLeaExecute.subst(iop) 692 693 class LeaOp(LdStOp): 694 def __init__(self, data, segment, addr, disp = 0, 695 dataSize="env.dataSize", addressSize="env.addressSize"): 696 super(LeaOp, self).__init__(data, segment, addr, disp, 697 dataSize, addressSize, "0", False, False, False) 698 self.className = "Lea" 699 self.mnemonic = "lea" 700 701 microopClasses["lea"] = LeaOp 702 703 704 iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
|
525 {"code": "xc->demapPage(EA, 0);", 526 "ea_code": calculateEA})
| 705 { "code": "xc->demapPage(EA, 0);", 706 "ea_code": calculateEA, 707 "memDataSize": "dataSize" })
|
527 header_output += MicroLeaDeclare.subst(iop) 528 decoder_output += MicroLdStOpConstructor.subst(iop) 529 exec_output += MicroLeaExecute.subst(iop) 530 531 class TiaOp(LdStOp): 532 def __init__(self, segment, addr, disp = 0, 533 dataSize="env.dataSize", 534 addressSize="env.addressSize"): 535 super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment, 536 addr, disp, dataSize, addressSize, "0", False, False, 537 False) 538 self.className = "Tia" 539 self.mnemonic = "tia" 540 541 microopClasses["tia"] = TiaOp 542 543 class CdaOp(LdStOp): 544 def __init__(self, segment, addr, disp = 0, 545 dataSize="env.dataSize", 546 addressSize="env.addressSize", atCPL0=False): 547 super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment, 548 addr, disp, dataSize, addressSize, "Request::NO_ACCESS", 549 atCPL0, False, False) 550 self.className = "Cda" 551 self.mnemonic = "cda" 552 553 microopClasses["cda"] = CdaOp 554}}; 555
| 708 header_output += MicroLeaDeclare.subst(iop) 709 decoder_output += MicroLdStOpConstructor.subst(iop) 710 exec_output += MicroLeaExecute.subst(iop) 711 712 class TiaOp(LdStOp): 713 def __init__(self, segment, addr, disp = 0, 714 dataSize="env.dataSize", 715 addressSize="env.addressSize"): 716 super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment, 717 addr, disp, dataSize, addressSize, "0", False, False, 718 False) 719 self.className = "Tia" 720 self.mnemonic = "tia" 721 722 microopClasses["tia"] = TiaOp 723 724 class CdaOp(LdStOp): 725 def __init__(self, segment, addr, disp = 0, 726 dataSize="env.dataSize", 727 addressSize="env.addressSize", atCPL0=False): 728 super(CdaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment, 729 addr, disp, dataSize, addressSize, "Request::NO_ACCESS", 730 atCPL0, False, False) 731 self.className = "Cda" 732 self.mnemonic = "cda" 733 734 microopClasses["cda"] = CdaOp 735}}; 736
|