mem.isa revision 2665
1// -*- mode:c++ -*- 2 3// Copyright (c) 2003-2005 The Regents of The University of Michigan 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer; 10// redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution; 13// neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28// 29// Authors: Gabe Black 30// Korey Sewell 31 32//////////////////////////////////////////////////////////////////// 33// 34// Memory-format instructions: LoadAddress, Load, Store 35// 36 37output header {{ 38 /** 39 * Base class for general Mips memory-format instructions. 40 */ 41 class Memory : public MipsStaticInst 42 { 43 protected: 44 45 /// Memory request flags. See mem_req_base.hh. 46 unsigned memAccessFlags; 47 /// Pointer to EAComp object. 48 const StaticInstPtr eaCompPtr; 49 /// Pointer to MemAcc object. 50 const StaticInstPtr memAccPtr; 51 52 /// Displacement for EA calculation (signed). 53 int32_t disp; 54 55 /// Constructor 56 Memory(const char *mnem, MachInst _machInst, OpClass __opClass, 57 StaticInstPtr _eaCompPtr = nullStaticInstPtr, 58 StaticInstPtr _memAccPtr = nullStaticInstPtr) 59 : MipsStaticInst(mnem, _machInst, __opClass), 60 memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), 61 disp(OFFSET) 62 { 63 //If Bit 15 is 1 then Sign Extend 64 int32_t temp = disp & 0x00008000; 65 66 if (temp > 0) { 67 disp |= 0xFFFF0000; 68 } 69 } 70 71 std::string 72 generateDisassembly(Addr pc, const SymbolTable *symtab) const; 73 74 public: 75 76 const StaticInstPtr &eaCompInst() const { return eaCompPtr; } 77 const StaticInstPtr &memAccInst() const { return memAccPtr; } 78 }; 79 80}}; 81 82 83output decoder {{ 84 std::string 85 Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const 86 { 87 return csprintf("%-10s %c%d,%d(r%d)", mnemonic, 88 flags[IsFloating] ? 'f' : 'r', RT, disp, RS); 89 } 90 91}}; 92 93def format LoadAddress(code) {{ 94 iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code)) 95 header_output = BasicDeclare.subst(iop) 96 decoder_output = BasicConstructor.subst(iop) 97 decode_block = BasicDecode.subst(iop) 98 exec_output = BasicExecute.subst(iop) 99}}; 100 101 102def template LoadStoreDeclare {{ 103 /** 104 * Static instruction class for "%(mnemonic)s". 105 */ 106 class %(class_name)s : public %(base_class)s 107 { 108 protected: 109 110 /** 111 * "Fake" effective address computation class for "%(mnemonic)s". 112 */ 113 class EAComp : public %(base_class)s 114 { 115 public: 116 /// Constructor 117 EAComp(MachInst machInst); 118 119 %(BasicExecDeclare)s 120 }; 121 122 /** 123 * "Fake" memory access instruction class for "%(mnemonic)s". 124 */ 125 class MemAcc : public %(base_class)s 126 { 127 public: 128 /// Constructor 129 MemAcc(MachInst machInst); 130 131 %(BasicExecDeclare)s 132 }; 133 134 public: 135 136 /// Constructor. 137 %(class_name)s(MachInst machInst); 138 139 %(BasicExecDeclare)s 140 141 %(InitiateAccDeclare)s 142 143 %(CompleteAccDeclare)s 144 }; 145}}; 146 147 148def template InitiateAccDeclare {{ 149 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 150}}; 151 152 153def template CompleteAccDeclare {{ 154 Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; 155}}; 156 157 158def template LoadStoreConstructor {{ 159 /** TODO: change op_class to AddrGenOp or something (requires 160 * creating new member of OpClass enum in op_class.hh, updating 161 * config files, etc.). */ 162 inline %(class_name)s::EAComp::EAComp(MachInst machInst) 163 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) 164 { 165 %(ea_constructor)s; 166 } 167 168 inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) 169 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) 170 { 171 %(memacc_constructor)s; 172 } 173 174 inline %(class_name)s::%(class_name)s(MachInst machInst) 175 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 176 new EAComp(machInst), new MemAcc(machInst)) 177 { 178 %(constructor)s; 179 } 180}}; 181 182 183def template EACompExecute {{ 184 Fault 185 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, 186 Trace::InstRecord *traceData) const 187 { 188 Addr EA; 189 Fault fault = NoFault; 190 191 %(fp_enable_check)s; 192 %(op_decl)s; 193 %(op_rd)s; 194 %(code)s; 195 196 if (fault == NoFault) { 197 %(op_wb)s; 198 xc->setEA(EA); 199 } 200 201 return fault; 202 } 203}}; 204 205def template LoadMemAccExecute {{ 206 Fault 207 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 208 Trace::InstRecord *traceData) const 209 { 210 Addr EA; 211 Fault fault = NoFault; 212 213 %(fp_enable_check)s; 214 %(op_decl)s; 215 %(op_rd)s; 216 EA = xc->getEA(); 217 218 if (fault == NoFault) { 219 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 220 %(code)s; 221 } 222 223 if (fault == NoFault) { 224 %(op_wb)s; 225 } 226 227 return fault; 228 } 229}}; 230 231 232def template LoadExecute {{ 233 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 234 Trace::InstRecord *traceData) const 235 { 236 Addr EA; 237 Fault fault = NoFault; 238 239 %(fp_enable_check)s; 240 %(op_decl)s; 241 %(op_rd)s; 242 %(ea_code)s; 243 244 if (fault == NoFault) { 245 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 246 %(memacc_code)s; 247 } 248 249 if (fault == NoFault) { 250 %(op_wb)s; 251 } 252 253 return fault; 254 } 255}}; 256 257 258def template LoadInitiateAcc {{ 259 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 260 Trace::InstRecord *traceData) const 261 { 262 Addr EA; 263 Fault fault = NoFault; 264 265 %(fp_enable_check)s; 266 %(op_src_decl)s; 267 %(op_rd)s; 268 %(ea_code)s; 269 270 if (fault == NoFault) { 271 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 272 } 273 274 return fault; 275 } 276}}; 277 278 279def template LoadCompleteAcc {{ 280 Fault %(class_name)s::completeAcc(uint8_t *data, 281 %(CPU_exec_context)s *xc, 282 Trace::InstRecord *traceData) const 283 { 284 Fault fault = NoFault; 285 286 %(fp_enable_check)s; 287 %(op_decl)s; 288 289 memcpy(&Mem, data, sizeof(Mem)); 290 291 if (fault == NoFault) { 292 %(memacc_code)s; 293 } 294 295 if (fault == NoFault) { 296 %(op_wb)s; 297 } 298 299 return fault; 300 } 301}}; 302 303 304def template StoreMemAccExecute {{ 305 Fault 306 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 307 Trace::InstRecord *traceData) const 308 { 309 Addr EA; 310 Fault fault = NoFault; 311 uint64_t write_result = 0; 312 313 %(fp_enable_check)s; 314 %(op_decl)s; 315 %(op_rd)s; 316 EA = xc->getEA(); 317 318 if (fault == NoFault) { 319 %(code)s; 320 } 321 322 if (fault == NoFault) { 323 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 324 memAccessFlags, &write_result); 325 if (traceData) { traceData->setData(Mem); } 326 } 327 328 if (fault == NoFault) { 329 %(postacc_code)s; 330 } 331 332 if (fault == NoFault) { 333 %(op_wb)s; 334 } 335 336 return fault; 337 } 338}}; 339 340 341def template StoreExecute {{ 342 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 343 Trace::InstRecord *traceData) const 344 { 345 Addr EA; 346 Fault fault = NoFault; 347 uint64_t write_result = 0; 348 349 %(fp_enable_check)s; 350 %(op_decl)s; 351 %(op_rd)s; 352 %(ea_code)s; 353 354 if (fault == NoFault) { 355 %(memacc_code)s; 356 } 357 358 if (fault == NoFault) { 359 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 360 memAccessFlags, &write_result); 361 if (traceData) { traceData->setData(Mem); } 362 } 363 364 if (fault == NoFault) { 365 %(postacc_code)s; 366 } 367 368 if (fault == NoFault) { 369 %(op_wb)s; 370 } 371 372 return fault; 373 } 374}}; 375 376def template StoreInitiateAcc {{ 377 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 378 Trace::InstRecord *traceData) const 379 { 380 Addr EA; 381 Fault fault = NoFault; 382 uint64_t write_result = 0; 383 384 %(fp_enable_check)s; 385 %(op_decl)s; 386 %(op_rd)s; 387 %(ea_code)s; 388 389 if (fault == NoFault) { 390 %(memacc_code)s; 391 } 392 393 if (fault == NoFault) { 394 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 395 memAccessFlags, &write_result); 396 if (traceData) { traceData->setData(Mem); } 397 } 398 399 return fault; 400 } 401}}; 402 403 404def template StoreCompleteAcc {{ 405 Fault %(class_name)s::completeAcc(uint8_t *data, 406 %(CPU_exec_context)s *xc, 407 Trace::InstRecord *traceData) const 408 { 409 Fault fault = NoFault; 410 uint64_t write_result = 0; 411 412 %(fp_enable_check)s; 413 %(op_dest_decl)s; 414 415 memcpy(&write_result, data, sizeof(write_result)); 416 417 if (fault == NoFault) { 418 %(postacc_code)s; 419 } 420 421 if (fault == NoFault) { 422 %(op_wb)s; 423 } 424 425 return fault; 426 } 427}}; 428 429// load instructions use Rt as dest, so check for 430// Rt == 31 to detect nops 431def template LoadNopCheckDecode {{ 432 { 433 MipsStaticInst *i = new %(class_name)s(machInst); 434 if (RT == 0) { 435 i = makeNop(i); 436 } 437 return i; 438 } 439}}; 440 441def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 442 mem_flags = [], inst_flags = []) {{ 443 (header_output, decoder_output, decode_block, exec_output) = \ 444 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 445 decode_template = LoadNopCheckDecode, 446 exec_template_base = 'Load') 447}}; 448 449 450def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 451 mem_flags = [], inst_flags = []) {{ 452 (header_output, decoder_output, decode_block, exec_output) = \ 453 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 454 exec_template_base = 'Store') 455}}; 456 457//FP loads are offloaded to these formats for now ... 458def format LoadFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 459 mem_flags = [], inst_flags = []) {{ 460 (header_output, decoder_output, decode_block, exec_output) = \ 461 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 462 decode_template = BasicDecode, 463 exec_template_base = 'Load') 464}}; 465 466 467def format StoreFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, 468 mem_flags = [], inst_flags = []) {{ 469 (header_output, decoder_output, decode_block, exec_output) = \ 470 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 471 exec_template_base = 'Store') 472}}; 473 474 475def format UnalignedStore(memacc_code, postacc_code, 476 ea_code = {{ EA = Rb + disp; }}, 477 mem_flags = [], inst_flags = []) {{ 478 (header_output, decoder_output, decode_block, exec_output) = \ 479 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 480 postacc_code, exec_template_base = 'Store') 481}}; 482