mem.isa revision 6303
1// -*- mode:c++ -*- 2 3// Copyright (c) 2007-2008 The Florida State University 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: Stephen Hines 30 31//////////////////////////////////////////////////////////////////// 32// 33// Memory-format instructions 34// 35 36def template LoadStoreDeclare {{ 37 /** 38 * Static instruction class for "%(mnemonic)s". 39 */ 40 class %(class_name)s : public %(base_class)s 41 { 42 protected: 43 44 /** 45 * "Fake" effective address computation class for "%(mnemonic)s". 46 */ 47 class EAComp : public %(base_class)s 48 { 49 public: 50 /// Constructor 51 EAComp(ExtMachInst machInst); 52 53 %(BasicExecDeclare)s 54 }; 55 56 /** 57 * "Fake" memory access instruction class for "%(mnemonic)s". 58 */ 59 class MemAcc : public %(base_class)s 60 { 61 public: 62 /// Constructor 63 MemAcc(ExtMachInst machInst); 64 65 %(BasicExecDeclare)s 66 }; 67 68 public: 69 70 /// Constructor. 71 %(class_name)s(ExtMachInst machInst); 72 73 %(BasicExecDeclare)s 74 75 %(InitiateAccDeclare)s 76 77 %(CompleteAccDeclare)s 78 }; 79}}; 80 81 82def template InitiateAccDeclare {{ 83 Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; 84}}; 85 86 87def template CompleteAccDeclare {{ 88 Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; 89}}; 90 91 92def template EACompConstructor {{ 93 inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst) 94 : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) 95 { 96 %(constructor)s; 97 } 98}}; 99 100 101def template MemAccConstructor {{ 102 inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst) 103 : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) 104 { 105 %(constructor)s; 106 } 107}}; 108 109 110def template LoadStoreConstructor {{ 111 inline %(class_name)s::%(class_name)s(ExtMachInst machInst) 112 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 113 new EAComp(machInst), new MemAcc(machInst)) 114 { 115 %(constructor)s; 116 } 117}}; 118 119 120def template EACompExecute {{ 121 Fault 122 %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, 123 Trace::InstRecord *traceData) const 124 { 125 Addr EA; 126 Fault fault = NoFault; 127 128 %(op_decl)s; 129 %(op_rd)s; 130 %(ea_code)s; 131 132 if (%(predicate_test)s) 133 { 134 if (fault == NoFault) { 135 %(op_wb)s; 136 xc->setEA(EA); 137 } 138 } 139 140 return fault; 141 } 142}}; 143 144def template LoadMemAccExecute {{ 145 Fault 146 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 147 Trace::InstRecord *traceData) const 148 { 149 Addr EA; 150 Fault fault = NoFault; 151 152 %(op_decl)s; 153 %(op_rd)s; 154 EA = xc->getEA(); 155 156 if (%(predicate_test)s) 157 { 158 if (fault == NoFault) { 159 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 160 %(memacc_code)s; 161 } 162 163 if (fault == NoFault) { 164 %(op_wb)s; 165 } 166 } 167 168 return fault; 169 } 170}}; 171 172 173def template LoadExecute {{ 174 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 175 Trace::InstRecord *traceData) const 176 { 177 Addr EA; 178 Fault fault = NoFault; 179 180 %(op_decl)s; 181 %(op_rd)s; 182 %(ea_code)s; 183 184 if (%(predicate_test)s) 185 { 186 if (fault == NoFault) { 187 fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); 188 %(memacc_code)s; 189 } 190 191 if (fault == NoFault) { 192 %(op_wb)s; 193 } 194 } 195 196 return fault; 197 } 198}}; 199 200 201def template LoadInitiateAcc {{ 202 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 203 Trace::InstRecord *traceData) const 204 { 205 Addr EA; 206 Fault fault = NoFault; 207 208 %(op_src_decl)s; 209 %(op_rd)s; 210 %(ea_code)s; 211 212 if (%(predicate_test)s) 213 { 214 if (fault == NoFault) { 215 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); 216 } 217 } 218 219 return fault; 220 } 221}}; 222 223 224def template LoadCompleteAcc {{ 225 Fault %(class_name)s::completeAcc(PacketPtr pkt, 226 %(CPU_exec_context)s *xc, 227 Trace::InstRecord *traceData) const 228 { 229 Fault fault = NoFault; 230 231 %(op_decl)s; 232 %(op_rd)s; 233 234 if (%(predicate_test)s) 235 { 236 // ARM instructions will not have a pkt if the predicate is false 237 Mem = pkt->get<typeof(Mem)>(); 238 239 if (fault == NoFault) { 240 %(memacc_code)s; 241 } 242 243 if (fault == NoFault) { 244 %(op_wb)s; 245 } 246 } 247 248 return fault; 249 } 250}}; 251 252 253def template StoreMemAccExecute {{ 254 Fault 255 %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 256 Trace::InstRecord *traceData) const 257 { 258 Addr EA; 259 Fault fault = NoFault; 260 261 %(op_decl)s; 262 %(op_rd)s; 263 264 if (%(predicate_test)s) 265 { 266 EA = xc->getEA(); 267 268 if (fault == NoFault) { 269 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 270 memAccessFlags, NULL); 271 if (traceData) { traceData->setData(Mem); } 272 } 273 274 if (fault == NoFault) { 275 %(op_wb)s; 276 } 277 } 278 279 return fault; 280 } 281}}; 282 283 284def template StoreExecute {{ 285 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 286 Trace::InstRecord *traceData) const 287 { 288 Addr EA; 289 Fault fault = NoFault; 290 291 %(op_decl)s; 292 %(op_rd)s; 293 %(ea_code)s; 294 295 if (%(predicate_test)s) 296 { 297 if (fault == NoFault) { 298 %(memacc_code)s; 299 } 300 301 if (fault == NoFault) { 302 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 303 memAccessFlags, NULL); 304 if (traceData) { traceData->setData(Mem); } 305 } 306 307 if (fault == NoFault) { 308 %(op_wb)s; 309 } 310 } 311 312 return fault; 313 } 314}}; 315 316def template StoreInitiateAcc {{ 317 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 318 Trace::InstRecord *traceData) const 319 { 320 Addr EA; 321 Fault fault = NoFault; 322 323 %(op_decl)s; 324 %(op_rd)s; 325 %(ea_code)s; 326 327 if (%(predicate_test)s) 328 { 329 if (fault == NoFault) { 330 %(memacc_code)s; 331 } 332 333 if (fault == NoFault) { 334 fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, 335 memAccessFlags, NULL); 336 if (traceData) { traceData->setData(Mem); } 337 } 338 339 // Need to write back any potential address register update 340 if (fault == NoFault) { 341 %(op_wb)s; 342 } 343 } 344 345 return fault; 346 } 347}}; 348 349 350def template StoreCompleteAcc {{ 351 Fault %(class_name)s::completeAcc(PacketPtr pkt, 352 %(CPU_exec_context)s *xc, 353 Trace::InstRecord *traceData) const 354 { 355 Fault fault = NoFault; 356 357 %(op_decl)s; 358 %(op_rd)s; 359 360 if (%(predicate_test)s) 361 { 362 if (fault == NoFault) { 363 %(op_wb)s; 364 } 365 } 366 367 return fault; 368 } 369}}; 370 371def template StoreCondCompleteAcc {{ 372 Fault %(class_name)s::completeAcc(PacketPtr pkt, 373 %(CPU_exec_context)s *xc, 374 Trace::InstRecord *traceData) const 375 { 376 Fault fault = NoFault; 377 378 %(op_dest_decl)s; 379 380 if (%(predicate_test)s) 381 { 382 if (fault == NoFault) { 383 %(op_wb)s; 384 } 385 } 386 387 return fault; 388 } 389}}; 390 391 392def template MiscMemAccExecute {{ 393 Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, 394 Trace::InstRecord *traceData) const 395 { 396 Addr EA; 397 Fault fault = NoFault; 398 399 %(op_decl)s; 400 %(op_rd)s; 401 402 if (%(predicate_test)s) 403 { 404 EA = xc->getEA(); 405 406 if (fault == NoFault) { 407 %(memacc_code)s; 408 } 409 } 410 411 return NoFault; 412 } 413}}; 414 415def template MiscExecute {{ 416 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 417 Trace::InstRecord *traceData) const 418 { 419 Addr EA; 420 Fault fault = NoFault; 421 422 %(op_decl)s; 423 %(op_rd)s; 424 %(ea_code)s; 425 426 if (%(predicate_test)s) 427 { 428 if (fault == NoFault) { 429 %(memacc_code)s; 430 } 431 } 432 433 return NoFault; 434 } 435}}; 436 437def template MiscInitiateAcc {{ 438 Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, 439 Trace::InstRecord *traceData) const 440 { 441 panic("Misc instruction does not support split access method!"); 442 return NoFault; 443 } 444}}; 445 446 447def template MiscCompleteAcc {{ 448 Fault %(class_name)s::completeAcc(PacketPtr pkt, 449 %(CPU_exec_context)s *xc, 450 Trace::InstRecord *traceData) const 451 { 452 panic("Misc instruction does not support split access method!"); 453 454 return NoFault; 455 } 456}}; 457 458let {{ 459 def buildPUBWLCase(p, u, b, w, l): 460 return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0) 461 462 def buildMode2Inst(p, u, b, w, l, suffix, offset): 463 mnem = ("str", "ldr")[l] 464 op = ("-", "+")[u] 465 offset = op + ArmGenericCodeSubs(offset); 466 mem = ("Mem", "Mem.ub")[b] 467 code = ("%s = Rd;", "Rd = %s;")[l] % mem 468 ea_code = "EA = Rn %s;" % ("", offset)[p] 469 if p == 0 or w == 1: 470 code += "Rn = Rn %s;" % offset 471 if p == 0 and w == 0: 472 # Here's where we'll tack on a flag to make this a usermode access. 473 mnem += "t" 474 type = ("Store", "Load")[l] 475 suffix = "_%s_P%dU%dB%dW%d" % (suffix, p, u, b, w) 476 if b == 1: 477 mnem += "b" 478 return LoadStoreBase(mnem, mnem.capitalize() + suffix, 479 ea_code, code, mem_flags = [], inst_flags = [], 480 exec_template_base = type.capitalize()) 481 482 def buildMode3Inst(p, u, i, w, type, code, mnem): 483 op = ("-", "+")[u] 484 offset = ("%s Rm", "%s hilo")[i] % op 485 ea_code = "EA = Rn %s;" % ("", offset)[p] 486 if p == 0 or w == 1: 487 code += "Rn = Rn %s;" % offset 488 suffix = "_P%dU%dI%dW%d" % (p, u, i, w) 489 return LoadStoreBase(mnem, mnem.capitalize() + suffix, 490 ea_code, code, mem_flags = [], inst_flags = [], 491 exec_template_base = type.capitalize()) 492}}; 493 494def format AddrMode2(suffix, offset) {{ 495 header_output = decoder_output = exec_output = "" 496 decode_block = "switch(PUBWL) {\n" 497 498 # Loop over all the values of p, u, b, w and l and build instructions and 499 # a decode block for them. 500 for p in (0, 1): 501 for u in (0, 1): 502 for b in (0, 1): 503 for w in (0, 1): 504 for l in (0, 1): 505 (new_header_output, 506 new_decoder_output, 507 new_decode_block, 508 new_exec_output) = buildMode2Inst(p, u, b, w, l, 509 suffix, offset) 510 header_output += new_header_output 511 decoder_output += new_decoder_output 512 exec_output += new_exec_output 513 decode_block += ''' 514 case %#x: 515 {%s} 516 break; 517 ''' % (buildPUBWLCase(p,u,b,w,l), new_decode_block) 518 decode_block += ''' 519 default: 520 return new Unknown(machInst); 521 break; 522 }''' 523}}; 524 525def format AddrMode3(l0Type, l0Code, l1Type, l1Code) {{ 526 l0Code = ArmGenericCodeSubs(l0Code); 527 l1Code = ArmGenericCodeSubs(l1Code); 528 529 header_output = decoder_output = exec_output = "" 530 decode_block = "switch(PUBWL) {\n" 531 (l0Mnem, l1Mnem) = name.split("_"); 532 533 # Loop over all the values of p, u, i, w and l and build instructions and 534 # a decode block for them. 535 for (l, type, code, mnem) in ((0, l0Type, l0Code, l0Mnem), 536 (1, l1Type, l1Code, l1Mnem)): 537 for p in (0, 1): 538 wset = (0, 1) 539 if (p == 0): 540 wset = (0,) 541 for u in (0, 1): 542 for i in (0, 1): 543 for w in wset: 544 (new_header_output, 545 new_decoder_output, 546 new_decode_block, 547 new_exec_output) = buildMode3Inst(p, u, i, w, 548 type, code, mnem) 549 header_output += new_header_output 550 decoder_output += new_decoder_output 551 exec_output += new_exec_output 552 decode_block += ''' 553 case %#x: 554 {%s} 555 break; 556 ''' % (buildPUBWLCase(p,u,i,w,l), new_decode_block) 557 558 decode_block += ''' 559 default: 560 return new Unknown(machInst); 561 break; 562 }''' 563}}; 564 565def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }}, 566 mem_flags = [], inst_flags = []) {{ 567 ea_code = ArmGenericCodeSubs(ea_code) 568 memacc_code = ArmGenericCodeSubs(memacc_code) 569 (header_output, decoder_output, decode_block, exec_output) = \ 570 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 571 decode_template = BasicDecode, 572 exec_template_base = 'Load') 573}}; 574 575def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }}, 576 mem_flags = [], inst_flags = []) {{ 577 ea_code = ArmGenericCodeSubs(ea_code) 578 memacc_code = ArmGenericCodeSubs(memacc_code) 579 (header_output, decoder_output, decode_block, exec_output) = \ 580 LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, 581 exec_template_base = 'Store') 582}}; 583 584