pseudo_inst.cc revision 8784
111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2010 ARM Limited 311308Santhony.gutierrez@amd.com * All rights reserved 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * The license below extends only to copyright in the software and shall 611308Santhony.gutierrez@amd.com * not be construed as granting a license to any other intellectual 711308Santhony.gutierrez@amd.com * property including but not limited to intellectual property relating 811308Santhony.gutierrez@amd.com * to a hardware implementation of the functionality of the software 911308Santhony.gutierrez@amd.com * licensed hereunder. You may use the software subject to the license 1011308Santhony.gutierrez@amd.com * terms below provided that you ensure that this notice is replicated 1111308Santhony.gutierrez@amd.com * unmodified and in its entirety in all distributions of the software, 1211308Santhony.gutierrez@amd.com * modified or unmodified, in source code or in binary form. 1311308Santhony.gutierrez@amd.com * 1411308Santhony.gutierrez@amd.com * Copyright (c) 2011 Advanced Micro Devices, Inc. 1511308Santhony.gutierrez@amd.com * Copyright (c) 2003-2006 The Regents of The University of Michigan 1611308Santhony.gutierrez@amd.com * All rights reserved. 1711308Santhony.gutierrez@amd.com * 1811308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 1911308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are 2011308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 2111308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer; 2211308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright 2311308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 2411308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution; 2511308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its 2611308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from 2711308Santhony.gutierrez@amd.com * this software without specific prior written permission. 2811308Santhony.gutierrez@amd.com * 2911308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3011308Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3111308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3211308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3311308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3411308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3511308Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3611308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3711308Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3811308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3911308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4011308Santhony.gutierrez@amd.com * 4111308Santhony.gutierrez@amd.com * Authors: Nathan Binkert 4211308Santhony.gutierrez@amd.com */ 4311308Santhony.gutierrez@amd.com 4411308Santhony.gutierrez@amd.com#include <fcntl.h> 4511308Santhony.gutierrez@amd.com#include <unistd.h> 4611308Santhony.gutierrez@amd.com 4711308Santhony.gutierrez@amd.com#include <cerrno> 4811308Santhony.gutierrez@amd.com#include <fstream> 4911308Santhony.gutierrez@amd.com#include <string> 5011308Santhony.gutierrez@amd.com 5111308Santhony.gutierrez@amd.com#include "arch/kernel_stats.hh" 5211308Santhony.gutierrez@amd.com#include "arch/vtophys.hh" 5311308Santhony.gutierrez@amd.com#include "base/debug.hh" 5411308Santhony.gutierrez@amd.com#include "config/full_system.hh" 5511308Santhony.gutierrez@amd.com#include "config/the_isa.hh" 5611308Santhony.gutierrez@amd.com#include "cpu/base.hh" 5711308Santhony.gutierrez@amd.com#include "cpu/quiesce_event.hh" 5811308Santhony.gutierrez@amd.com#include "cpu/thread_context.hh" 5911308Santhony.gutierrez@amd.com#include "debug/Loader.hh" 6011308Santhony.gutierrez@amd.com#include "debug/Quiesce.hh" 6111308Santhony.gutierrez@amd.com#include "debug/WorkItems.hh" 6211308Santhony.gutierrez@amd.com#include "params/BaseCPU.hh" 6311308Santhony.gutierrez@amd.com#include "sim/full_system.hh" 6411308Santhony.gutierrez@amd.com#include "sim/pseudo_inst.hh" 6511308Santhony.gutierrez@amd.com#include "sim/serialize.hh" 6611308Santhony.gutierrez@amd.com#include "sim/sim_events.hh" 6711308Santhony.gutierrez@amd.com#include "sim/sim_exit.hh" 6811308Santhony.gutierrez@amd.com#include "sim/stat_control.hh" 6911308Santhony.gutierrez@amd.com#include "sim/stats.hh" 7011308Santhony.gutierrez@amd.com#include "sim/system.hh" 7111308Santhony.gutierrez@amd.com#include "sim/vptr.hh" 7211308Santhony.gutierrez@amd.com 7311308Santhony.gutierrez@amd.comusing namespace std; 7411308Santhony.gutierrez@amd.com 7511308Santhony.gutierrez@amd.comusing namespace Stats; 7611308Santhony.gutierrez@amd.comusing namespace TheISA; 7711308Santhony.gutierrez@amd.com 7811308Santhony.gutierrez@amd.comnamespace PseudoInst { 7911308Santhony.gutierrez@amd.com 8011308Santhony.gutierrez@amd.comstatic inline void 8111308Santhony.gutierrez@amd.companicFsOnlyPseudoInst(const char *name) 8211308Santhony.gutierrez@amd.com{ 8311308Santhony.gutierrez@amd.com panic("Pseudo inst \"%s\" is only available in Full System mode."); 8411308Santhony.gutierrez@amd.com} 8511308Santhony.gutierrez@amd.com 8611308Santhony.gutierrez@amd.comvoid 8711308Santhony.gutierrez@amd.comarm(ThreadContext *tc) 8811308Santhony.gutierrez@amd.com{ 8911308Santhony.gutierrez@amd.com if (FullSystem) { 9011308Santhony.gutierrez@amd.com if (tc->getKernelStats()) 9111308Santhony.gutierrez@amd.com tc->getKernelStats()->arm(); 9211308Santhony.gutierrez@amd.com } else { 9311308Santhony.gutierrez@amd.com panicFsOnlyPseudoInst("arm"); 9411308Santhony.gutierrez@amd.com } 9511308Santhony.gutierrez@amd.com} 9611308Santhony.gutierrez@amd.com 9711308Santhony.gutierrez@amd.comvoid 9811308Santhony.gutierrez@amd.comquiesce(ThreadContext *tc) 9911308Santhony.gutierrez@amd.com{ 10011308Santhony.gutierrez@amd.com if (FullSystem) { 10111308Santhony.gutierrez@amd.com if (!tc->getCpuPtr()->params()->do_quiesce) 10211308Santhony.gutierrez@amd.com return; 10311308Santhony.gutierrez@amd.com 10411308Santhony.gutierrez@amd.com DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name()); 10511308Santhony.gutierrez@amd.com 10611308Santhony.gutierrez@amd.com tc->suspend(); 10711308Santhony.gutierrez@amd.com if (tc->getKernelStats()) 10811308Santhony.gutierrez@amd.com tc->getKernelStats()->quiesce(); 10911308Santhony.gutierrez@amd.com } else { 11011308Santhony.gutierrez@amd.com panicFsOnlyPseudoInst("quiesce"); 11111308Santhony.gutierrez@amd.com } 11211308Santhony.gutierrez@amd.com} 11311308Santhony.gutierrez@amd.com 11411308Santhony.gutierrez@amd.comvoid 11511308Santhony.gutierrez@amd.comquiesceSkip(ThreadContext *tc) 11611308Santhony.gutierrez@amd.com{ 11711308Santhony.gutierrez@amd.com if (FullSystem) { 11811308Santhony.gutierrez@amd.com BaseCPU *cpu = tc->getCpuPtr(); 11911308Santhony.gutierrez@amd.com 12011308Santhony.gutierrez@amd.com if (!cpu->params()->do_quiesce) 12111308Santhony.gutierrez@amd.com return; 12211308Santhony.gutierrez@amd.com 12311308Santhony.gutierrez@amd.com EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); 12411308Santhony.gutierrez@amd.com 12511308Santhony.gutierrez@amd.com Tick resume = curTick() + 1; 12611308Santhony.gutierrez@amd.com 12711308Santhony.gutierrez@amd.com cpu->reschedule(quiesceEvent, resume, true); 12811308Santhony.gutierrez@amd.com 12911308Santhony.gutierrez@amd.com DPRINTF(Quiesce, "%s: quiesceSkip() until %d\n", 13011308Santhony.gutierrez@amd.com cpu->name(), resume); 13111308Santhony.gutierrez@amd.com 13211308Santhony.gutierrez@amd.com tc->suspend(); 13311308Santhony.gutierrez@amd.com if (tc->getKernelStats()) 13411639Salexandru.dutu@amd.com tc->getKernelStats()->quiesce(); 13511308Santhony.gutierrez@amd.com } else { 13611308Santhony.gutierrez@amd.com panicFsOnlyPseudoInst("quiesceSkip"); 13711534Sjohn.kalamatianos@amd.com } 13811308Santhony.gutierrez@amd.com} 13911639Salexandru.dutu@amd.com 14011308Santhony.gutierrez@amd.comvoid 14111308Santhony.gutierrez@amd.comquiesceNs(ThreadContext *tc, uint64_t ns) 14211308Santhony.gutierrez@amd.com{ 14311308Santhony.gutierrez@amd.com if (FullSystem) { 14411308Santhony.gutierrez@amd.com BaseCPU *cpu = tc->getCpuPtr(); 14511308Santhony.gutierrez@amd.com 14611308Santhony.gutierrez@amd.com if (!cpu->params()->do_quiesce || ns == 0) 14711308Santhony.gutierrez@amd.com return; 14811308Santhony.gutierrez@amd.com 14911308Santhony.gutierrez@amd.com EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); 15011308Santhony.gutierrez@amd.com 15111308Santhony.gutierrez@amd.com Tick resume = curTick() + SimClock::Int::ns * ns; 15211639Salexandru.dutu@amd.com 15311308Santhony.gutierrez@amd.com cpu->reschedule(quiesceEvent, resume, true); 15411308Santhony.gutierrez@amd.com 15511308Santhony.gutierrez@amd.com DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n", 15611639Salexandru.dutu@amd.com cpu->name(), ns, resume); 15711308Santhony.gutierrez@amd.com 15811308Santhony.gutierrez@amd.com tc->suspend(); 15911639Salexandru.dutu@amd.com if (tc->getKernelStats()) 16011308Santhony.gutierrez@amd.com tc->getKernelStats()->quiesce(); 16111308Santhony.gutierrez@amd.com } else { 16211308Santhony.gutierrez@amd.com panicFsOnlyPseudoInst("quiesceNs"); 16311308Santhony.gutierrez@amd.com } 16411308Santhony.gutierrez@amd.com} 16511308Santhony.gutierrez@amd.com 16611308Santhony.gutierrez@amd.comvoid 16711308Santhony.gutierrez@amd.comquiesceCycles(ThreadContext *tc, uint64_t cycles) 16811308Santhony.gutierrez@amd.com{ 16911308Santhony.gutierrez@amd.com if (FullSystem) { 17011308Santhony.gutierrez@amd.com BaseCPU *cpu = tc->getCpuPtr(); 17111308Santhony.gutierrez@amd.com 17211308Santhony.gutierrez@amd.com if (!cpu->params()->do_quiesce || cycles == 0) 17311308Santhony.gutierrez@amd.com return; 17411308Santhony.gutierrez@amd.com 17511308Santhony.gutierrez@amd.com EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent(); 17611308Santhony.gutierrez@amd.com 17711308Santhony.gutierrez@amd.com Tick resume = curTick() + cpu->ticks(cycles); 17811308Santhony.gutierrez@amd.com 17911308Santhony.gutierrez@amd.com cpu->reschedule(quiesceEvent, resume, true); 18011308Santhony.gutierrez@amd.com 18111308Santhony.gutierrez@amd.com DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n", 18211692Santhony.gutierrez@amd.com cpu->name(), cycles, resume); 18311692Santhony.gutierrez@amd.com 18411692Santhony.gutierrez@amd.com tc->suspend(); 18511308Santhony.gutierrez@amd.com if (tc->getKernelStats()) 18611308Santhony.gutierrez@amd.com tc->getKernelStats()->quiesce(); 18711308Santhony.gutierrez@amd.com } else { 18811308Santhony.gutierrez@amd.com panicFsOnlyPseudoInst("quiesceCycles"); 18911308Santhony.gutierrez@amd.com } 19011308Santhony.gutierrez@amd.com} 19111308Santhony.gutierrez@amd.com 19211308Santhony.gutierrez@amd.comuint64_t 19311308Santhony.gutierrez@amd.comquiesceTime(ThreadContext *tc) 19411308Santhony.gutierrez@amd.com{ 19511308Santhony.gutierrez@amd.com if (FullSystem) { 19611308Santhony.gutierrez@amd.com return (tc->readLastActivate() - tc->readLastSuspend()) / 19711308Santhony.gutierrez@amd.com SimClock::Int::ns; 19811308Santhony.gutierrez@amd.com } else { 19911308Santhony.gutierrez@amd.com panicFsOnlyPseudoInst("quiesceTime"); 20011308Santhony.gutierrez@amd.com return 0; 20111308Santhony.gutierrez@amd.com } 20211308Santhony.gutierrez@amd.com} 20311308Santhony.gutierrez@amd.com 20411308Santhony.gutierrez@amd.comuint64_t 20511639Salexandru.dutu@amd.comrpns(ThreadContext *tc) 20611639Salexandru.dutu@amd.com{ 20711308Santhony.gutierrez@amd.com return curTick() / SimClock::Int::ns; 20811308Santhony.gutierrez@amd.com} 20911308Santhony.gutierrez@amd.com 210void 211wakeCPU(ThreadContext *tc, uint64_t cpuid) 212{ 213 System *sys = tc->getSystemPtr(); 214 ThreadContext *other_tc = sys->threadContexts[cpuid]; 215 if (other_tc->status() == ThreadContext::Suspended) 216 other_tc->activate(); 217} 218 219void 220m5exit(ThreadContext *tc, Tick delay) 221{ 222 Tick when = curTick() + delay * SimClock::Int::ns; 223 exitSimLoop("m5_exit instruction encountered", 0, when); 224} 225 226void 227loadsymbol(ThreadContext *tc) 228{ 229 if (FullSystem) { 230 const string &filename = tc->getCpuPtr()->system->params()->symbolfile; 231 if (filename.empty()) { 232 return; 233 } 234 235 std::string buffer; 236 ifstream file(filename.c_str()); 237 238 if (!file) 239 fatal("file error: Can't open symbol table file %s\n", filename); 240 241 while (!file.eof()) { 242 getline(file, buffer); 243 244 if (buffer.empty()) 245 continue; 246 247 string::size_type idx = buffer.find(' '); 248 if (idx == string::npos) 249 continue; 250 251 string address = "0x" + buffer.substr(0, idx); 252 eat_white(address); 253 if (address.empty()) 254 continue; 255 256 // Skip over letter and space 257 string symbol = buffer.substr(idx + 3); 258 eat_white(symbol); 259 if (symbol.empty()) 260 continue; 261 262 Addr addr; 263 if (!to_number(address, addr)) 264 continue; 265 266 if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol)) 267 continue; 268 269 270 DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); 271 } 272 file.close(); 273 } else { 274 panicFsOnlyPseudoInst("loadsymbol"); 275 } 276} 277 278void 279addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr) 280{ 281 if (FullSystem) { 282 char symb[100]; 283 CopyStringOut(tc, symb, symbolAddr, 100); 284 std::string symbol(symb); 285 286 DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr); 287 288 tc->getSystemPtr()->kernelSymtab->insert(addr,symbol); 289 debugSymbolTable->insert(addr,symbol); 290 } else { 291 panicFsOnlyPseudoInst("addSymbol"); 292 } 293} 294 295uint64_t 296initParam(ThreadContext *tc) 297{ 298 if (FullSystem) { 299 return tc->getCpuPtr()->system->init_param; 300 } else { 301 panicFsOnlyPseudoInst("initParam"); 302 return 0; 303 } 304} 305 306 307void 308resetstats(ThreadContext *tc, Tick delay, Tick period) 309{ 310 if (!tc->getCpuPtr()->params()->do_statistics_insts) 311 return; 312 313 314 Tick when = curTick() + delay * SimClock::Int::ns; 315 Tick repeat = period * SimClock::Int::ns; 316 317 Stats::schedStatEvent(false, true, when, repeat); 318} 319 320void 321dumpstats(ThreadContext *tc, Tick delay, Tick period) 322{ 323 if (!tc->getCpuPtr()->params()->do_statistics_insts) 324 return; 325 326 327 Tick when = curTick() + delay * SimClock::Int::ns; 328 Tick repeat = period * SimClock::Int::ns; 329 330 Stats::schedStatEvent(true, false, when, repeat); 331} 332 333void 334dumpresetstats(ThreadContext *tc, Tick delay, Tick period) 335{ 336 if (!tc->getCpuPtr()->params()->do_statistics_insts) 337 return; 338 339 340 Tick when = curTick() + delay * SimClock::Int::ns; 341 Tick repeat = period * SimClock::Int::ns; 342 343 Stats::schedStatEvent(true, true, when, repeat); 344} 345 346void 347m5checkpoint(ThreadContext *tc, Tick delay, Tick period) 348{ 349 if (!tc->getCpuPtr()->params()->do_checkpoint_insts) 350 return; 351 352 Tick when = curTick() + delay * SimClock::Int::ns; 353 Tick repeat = period * SimClock::Int::ns; 354 355 exitSimLoop("checkpoint", 0, when, repeat); 356} 357 358uint64_t 359readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset) 360{ 361 if (FullSystem) { 362 const string &file = tc->getSystemPtr()->params()->readfile; 363 if (file.empty()) { 364 return ULL(0); 365 } 366 367 uint64_t result = 0; 368 369 int fd = ::open(file.c_str(), O_RDONLY, 0); 370 if (fd < 0) 371 panic("could not open file %s\n", file); 372 373 if (::lseek(fd, offset, SEEK_SET) < 0) 374 panic("could not seek: %s", strerror(errno)); 375 376 char *buf = new char[len]; 377 char *p = buf; 378 while (len > 0) { 379 int bytes = ::read(fd, p, len); 380 if (bytes <= 0) 381 break; 382 383 p += bytes; 384 result += bytes; 385 len -= bytes; 386 } 387 388 close(fd); 389 CopyIn(tc, vaddr, buf, result); 390 delete [] buf; 391 return result; 392 } else { 393 panicFsOnlyPseudoInst("readfile"); 394 return 0; 395 } 396} 397 398void 399debugbreak(ThreadContext *tc) 400{ 401 Debug::breakpoint(); 402} 403 404void 405switchcpu(ThreadContext *tc) 406{ 407 exitSimLoop("switchcpu"); 408} 409 410// 411// This function is executed when annotated work items begin. Depending on 412// what the user specified at the command line, the simulation may exit and/or 413// take a checkpoint when a certain work item begins. 414// 415void 416workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid) 417{ 418 tc->getCpuPtr()->workItemBegin(); 419 System *sys = tc->getSystemPtr(); 420 const System::Params *params = sys->params(); 421 422 DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid, 423 threadid); 424 425 // 426 // If specified, determine if this is the specific work item the user 427 // identified 428 // 429 if (params->work_item_id == -1 || params->work_item_id == workid) { 430 431 uint64_t systemWorkBeginCount = sys->incWorkItemsBegin(); 432 int cpuId = tc->getCpuPtr()->cpuId(); 433 434 if (params->work_cpus_ckpt_count != 0 && 435 sys->markWorkItem(cpuId) >= params->work_cpus_ckpt_count) { 436 // 437 // If active cpus equals checkpoint count, create checkpoint 438 // 439 exitSimLoop("checkpoint"); 440 } 441 442 if (systemWorkBeginCount == params->work_begin_ckpt_count) { 443 // 444 // Note: the string specified as the cause of the exit event must 445 // exactly equal "checkpoint" inorder to create a checkpoint 446 // 447 exitSimLoop("checkpoint"); 448 } 449 450 if (systemWorkBeginCount == params->work_begin_exit_count) { 451 // 452 // If a certain number of work items started, exit simulation 453 // 454 exitSimLoop("work started count reach"); 455 } 456 457 if (cpuId == params->work_begin_cpu_id_exit) { 458 // 459 // If work started on the cpu id specified, exit simulation 460 // 461 exitSimLoop("work started on specific cpu"); 462 } 463 } 464} 465 466// 467// This function is executed when annotated work items end. Depending on 468// what the user specified at the command line, the simulation may exit and/or 469// take a checkpoint when a certain work item ends. 470// 471void 472workend(ThreadContext *tc, uint64_t workid, uint64_t threadid) 473{ 474 tc->getCpuPtr()->workItemEnd(); 475 System *sys = tc->getSystemPtr(); 476 const System::Params *params = sys->params(); 477 478 DPRINTF(WorkItems, "Work End workid: %d, threadid %d\n", workid, threadid); 479 480 // 481 // If specified, determine if this is the specific work item the user 482 // identified 483 // 484 if (params->work_item_id == -1 || params->work_item_id == workid) { 485 486 uint64_t systemWorkEndCount = sys->incWorkItemsEnd(); 487 int cpuId = tc->getCpuPtr()->cpuId(); 488 489 if (params->work_cpus_ckpt_count != 0 && 490 sys->markWorkItem(cpuId) >= params->work_cpus_ckpt_count) { 491 // 492 // If active cpus equals checkpoint count, create checkpoint 493 // 494 exitSimLoop("checkpoint"); 495 } 496 497 if (params->work_end_ckpt_count != 0 && 498 systemWorkEndCount == params->work_end_ckpt_count) { 499 // 500 // If total work items completed equals checkpoint count, create 501 // checkpoint 502 // 503 exitSimLoop("checkpoint"); 504 } 505 506 if (params->work_end_exit_count != 0 && 507 systemWorkEndCount == params->work_end_exit_count) { 508 // 509 // If total work items completed equals exit count, exit simulation 510 // 511 exitSimLoop("work items exit count reached"); 512 } 513 } 514} 515 516} // namespace PseudoInst 517