pseudo_inst.cc revision 8232
11689SN/A/*
22325SN/A * Copyright (c) 2010 ARM Limited
31689SN/A * All rights reserved
41689SN/A *
51689SN/A * The license below extends only to copyright in the software and shall
61689SN/A * not be construed as granting a license to any other intellectual
71689SN/A * property including but not limited to intellectual property relating
81689SN/A * to a hardware implementation of the functionality of the software
91689SN/A * licensed hereunder.  You may use the software subject to the license
101689SN/A * terms below provided that you ensure that this notice is replicated
111689SN/A * unmodified and in its entirety in all distributions of the software,
121689SN/A * modified or unmodified, in source code or in binary form.
131689SN/A *
141689SN/A * Copyright (c) 2003-2006 The Regents of The University of Michigan
151689SN/A * All rights reserved.
161689SN/A *
171689SN/A * Redistribution and use in source and binary forms, with or without
181689SN/A * modification, are permitted provided that the following conditions are
191689SN/A * met: redistributions of source code must retain the above copyright
201689SN/A * notice, this list of conditions and the following disclaimer;
211689SN/A * redistributions in binary form must reproduce the above copyright
221689SN/A * notice, this list of conditions and the following disclaimer in the
231689SN/A * documentation and/or other materials provided with the distribution;
241689SN/A * neither the name of the copyright holders nor the names of its
251689SN/A * contributors may be used to endorse or promote products derived from
261689SN/A * this software without specific prior written permission.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292756Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
301689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
311689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
321858SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332733Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
341858SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
351858SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362356SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
371060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
381060SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
391060SN/A *
401060SN/A * Authors: Nathan Binkert
411060SN/A */
422325SN/A
432683Sktlim@umich.edu#include <fcntl.h>
442680Sktlim@umich.edu#include <unistd.h>
452817Sksewell@umich.edu
461717SN/A#include <cerrno>
471060SN/A#include <fstream>
482325SN/A#include <string>
492292SN/A
502292SN/A#include "arch/vtophys.hh"
512794Sktlim@umich.edu#include "base/debug.hh"
522794Sktlim@umich.edu#include "config/full_system.hh"
532794Sktlim@umich.edu#include "config/the_isa.hh"
542794Sktlim@umich.edu#include "cpu/base.hh"
551060SN/A#include "cpu/quiesce_event.hh"
562669Sktlim@umich.edu#include "cpu/thread_context.hh"
571060SN/A#include "debug/Loader.hh"
582733Sktlim@umich.edu#include "debug/Quiesce.hh"
592292SN/A#include "debug/WorkItems.hh"
601060SN/A#include "params/BaseCPU.hh"
611060SN/A#include "sim/pseudo_inst.hh"
621060SN/A#include "sim/serialize.hh"
632292SN/A#include "sim/sim_events.hh"
642733Sktlim@umich.edu#include "sim/sim_exit.hh"
652292SN/A#include "sim/stat_control.hh"
662292SN/A#include "sim/stats.hh"
672292SN/A#include "sim/system.hh"
682292SN/A
691060SN/A#if FULL_SYSTEM
701755SN/A#include "arch/kernel_stats.hh"
711060SN/A#include "sim/vptr.hh"
721060SN/A#endif
731060SN/A
741060SN/Ausing namespace std;
751060SN/A
761060SN/Ausing namespace Stats;
771755SN/Ausing namespace TheISA;
781060SN/A
791060SN/Anamespace PseudoInst {
801060SN/A
811060SN/A#if FULL_SYSTEM
821060SN/A
831060SN/Avoid
841755SN/Aarm(ThreadContext *tc)
851060SN/A{
861755SN/A    if (tc->getKernelStats())
871060SN/A        tc->getKernelStats()->arm();
881060SN/A}
891060SN/A
902829Sksewell@umich.eduvoid
913221Sktlim@umich.eduquiesce(ThreadContext *tc)
922829Sksewell@umich.edu{
932829Sksewell@umich.edu    if (!tc->getCpuPtr()->params()->do_quiesce)
942829Sksewell@umich.edu        return;
952829Sksewell@umich.edu
962829Sksewell@umich.edu    DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
972829Sksewell@umich.edu
982829Sksewell@umich.edu    tc->suspend();
992829Sksewell@umich.edu    if (tc->getKernelStats())
1002829Sksewell@umich.edu        tc->getKernelStats()->quiesce();
1012829Sksewell@umich.edu}
1022829Sksewell@umich.edu
1032829Sksewell@umich.eduvoid
1042829Sksewell@umich.eduquiesceSkip(ThreadContext *tc)
1052829Sksewell@umich.edu{
1062829Sksewell@umich.edu    BaseCPU *cpu = tc->getCpuPtr();
1072829Sksewell@umich.edu
1082829Sksewell@umich.edu    if (!cpu->params()->do_quiesce)
1092829Sksewell@umich.edu        return;
1102829Sksewell@umich.edu
1112829Sksewell@umich.edu    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
1122829Sksewell@umich.edu
1132829Sksewell@umich.edu    Tick resume = curTick() + 1;
1142829Sksewell@umich.edu
1152829Sksewell@umich.edu    cpu->reschedule(quiesceEvent, resume, true);
1162829Sksewell@umich.edu
1172829Sksewell@umich.edu    DPRINTF(Quiesce, "%s: quiesceSkip() until %d\n",
1182829Sksewell@umich.edu            cpu->name(), resume);
1192875Sksewell@umich.edu
1202875Sksewell@umich.edu    tc->suspend();
1212875Sksewell@umich.edu    if (tc->getKernelStats())
1222875Sksewell@umich.edu        tc->getKernelStats()->quiesce();
1232875Sksewell@umich.edu}
1242875Sksewell@umich.edu
1252875Sksewell@umich.eduvoid
1262875Sksewell@umich.eduquiesceNs(ThreadContext *tc, uint64_t ns)
1272875Sksewell@umich.edu{
1282875Sksewell@umich.edu    BaseCPU *cpu = tc->getCpuPtr();
1292875Sksewell@umich.edu
1302875Sksewell@umich.edu    if (!cpu->params()->do_quiesce || ns == 0)
1312875Sksewell@umich.edu        return;
1322875Sksewell@umich.edu
1332875Sksewell@umich.edu    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
1342875Sksewell@umich.edu
1352875Sksewell@umich.edu    Tick resume = curTick() + SimClock::Int::ns * ns;
1362875Sksewell@umich.edu
1372875Sksewell@umich.edu    cpu->reschedule(quiesceEvent, resume, true);
1383221Sktlim@umich.edu
1393221Sktlim@umich.edu    DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
1402875Sksewell@umich.edu            cpu->name(), ns, resume);
1412875Sksewell@umich.edu
1422875Sksewell@umich.edu    tc->suspend();
1432875Sksewell@umich.edu    if (tc->getKernelStats())
1442875Sksewell@umich.edu        tc->getKernelStats()->quiesce();
1452875Sksewell@umich.edu}
1462875Sksewell@umich.edu
1472875Sksewell@umich.eduvoid
1482875Sksewell@umich.eduquiesceCycles(ThreadContext *tc, uint64_t cycles)
1492875Sksewell@umich.edu{
1502292SN/A    BaseCPU *cpu = tc->getCpuPtr();
1512733Sktlim@umich.edu
1521060SN/A    if (!cpu->params()->do_quiesce || cycles == 0)
1532292SN/A        return;
1541060SN/A
1551060SN/A    EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
1561060SN/A
1571060SN/A    Tick resume = curTick() + cpu->ticks(cycles);
1581060SN/A
1591060SN/A    cpu->reschedule(quiesceEvent, resume, true);
1602292SN/A
1611060SN/A    DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
1622831Sksewell@umich.edu            cpu->name(), cycles, resume);
1632292SN/A
1642292SN/A    tc->suspend();
1651060SN/A    if (tc->getKernelStats())
1662292SN/A        tc->getKernelStats()->quiesce();
1672292SN/A}
1682292SN/A
1691060SN/Auint64_t
1702831Sksewell@umich.eduquiesceTime(ThreadContext *tc)
1712292SN/A{
1722292SN/A    return (tc->readLastActivate() - tc->readLastSuspend()) /
1732292SN/A        SimClock::Int::ns;
1742292SN/A}
1751060SN/A
1762873Sktlim@umich.edu#endif
1772873Sktlim@umich.edu
1782873Sktlim@umich.eduuint64_t
1792873Sktlim@umich.edurpns(ThreadContext *tc)
1802873Sktlim@umich.edu{
1812873Sktlim@umich.edu    return curTick() / SimClock::Int::ns;
1822873Sktlim@umich.edu}
1832873Sktlim@umich.edu
1841060SN/Avoid
1851060SN/AwakeCPU(ThreadContext *tc, uint64_t cpuid)
1861858SN/A{
1872292SN/A    System *sys = tc->getSystemPtr();
1881060SN/A    ThreadContext *other_tc = sys->threadContexts[cpuid];
1891060SN/A    if (other_tc->status() == ThreadContext::Suspended)
1902292SN/A        other_tc->activate();
1912843Sktlim@umich.edu}
1922316SN/A
1932316SN/Avoid
1941060SN/Am5exit(ThreadContext *tc, Tick delay)
1953221Sktlim@umich.edu{
1963221Sktlim@umich.edu    Tick when = curTick() + delay * SimClock::Int::ns;
1973221Sktlim@umich.edu    exitSimLoop("m5_exit instruction encountered", 0, when);
1983221Sktlim@umich.edu}
1993221Sktlim@umich.edu
2001681SN/A#if FULL_SYSTEM
2012733Sktlim@umich.edu
2022733Sktlim@umich.eduvoid
2032794Sktlim@umich.eduloadsymbol(ThreadContext *tc)
2042733Sktlim@umich.edu{
2052316SN/A    const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
2062316SN/A    if (filename.empty()) {
2072316SN/A        return;
2082316SN/A    }
2092316SN/A
2102316SN/A    std::string buffer;
2112794Sktlim@umich.edu    ifstream file(filename.c_str());
2122794Sktlim@umich.edu
2132794Sktlim@umich.edu    if (!file)
2142316SN/A        fatal("file error: Can't open symbol table file %s\n", filename);
2152316SN/A
2161858SN/A    while (!file.eof()) {
2172292SN/A        getline(file, buffer);
2182292SN/A
2191681SN/A        if (buffer.empty())
2201681SN/A            continue;
2212325SN/A
2222325SN/A        string::size_type idx = buffer.find(' ');
2232325SN/A        if (idx == string::npos)
2241060SN/A            continue;
2252292SN/A
2262292SN/A        string address = "0x" + buffer.substr(0, idx);
2272292SN/A        eat_white(address);
2282292SN/A        if (address.empty())
2292292SN/A            continue;
2302292SN/A
2311060SN/A        // Skip over letter and space
2321060SN/A        string symbol = buffer.substr(idx + 3);
2331060SN/A        eat_white(symbol);
2341060SN/A        if (symbol.empty())
2351060SN/A            continue;
2361060SN/A
2371060SN/A        Addr addr;
2381060SN/A        if (!to_number(address, addr))
2391060SN/A            continue;
2401060SN/A
2411060SN/A        if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
2422292SN/A            continue;
2431060SN/A
2441060SN/A
2451060SN/A        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
2461060SN/A    }
2471060SN/A    file.close();
2481060SN/A}
2491060SN/A
2501060SN/Avoid
2512292SN/Aaddsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
2522292SN/A{
2532292SN/A    char symb[100];
2542292SN/A    CopyStringOut(tc, symb, symbolAddr, 100);
2552292SN/A    std::string symbol(symb);
2562307SN/A
2572831Sksewell@umich.edu    DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
2582831Sksewell@umich.edu
2592831Sksewell@umich.edu    tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
2602831Sksewell@umich.edu    debugSymbolTable->insert(addr,symbol);
2612831Sksewell@umich.edu}
2622831Sksewell@umich.edu
2632292SN/A#endif
2642307SN/A
2652292SN/A
2662292SN/Avoid
2672316SN/Aresetstats(ThreadContext *tc, Tick delay, Tick period)
2682292SN/A{
2692292SN/A    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2702292SN/A        return;
2712292SN/A
2722292SN/A
2732292SN/A    Tick when = curTick() + delay * SimClock::Int::ns;
2741060SN/A    Tick repeat = period * SimClock::Int::ns;
2752292SN/A
2762292SN/A    Stats::schedStatEvent(false, true, when, repeat);
2771060SN/A}
2782292SN/A
2792307SN/Avoid
2802292SN/Adumpstats(ThreadContext *tc, Tick delay, Tick period)
2812292SN/A{
2822292SN/A    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2832325SN/A        return;
2842292SN/A
2852292SN/A
2862292SN/A    Tick when = curTick() + delay * SimClock::Int::ns;
2872325SN/A    Tick repeat = period * SimClock::Int::ns;
2882292SN/A
2892292SN/A    Stats::schedStatEvent(true, false, when, repeat);
2902292SN/A}
2912292SN/A
2922292SN/Avoid
2932292SN/Adumpresetstats(ThreadContext *tc, Tick delay, Tick period)
2942292SN/A{
2952292SN/A    if (!tc->getCpuPtr()->params()->do_statistics_insts)
2962292SN/A        return;
2972292SN/A
2982292SN/A
2992325SN/A    Tick when = curTick() + delay * SimClock::Int::ns;
3002292SN/A    Tick repeat = period * SimClock::Int::ns;
3012292SN/A
3022292SN/A    Stats::schedStatEvent(true, true, when, repeat);
3032325SN/A}
3042292SN/A
3052292SN/Avoid
3062292SN/Am5checkpoint(ThreadContext *tc, Tick delay, Tick period)
3072292SN/A{
3082292SN/A    if (!tc->getCpuPtr()->params()->do_checkpoint_insts)
3092292SN/A        return;
3102292SN/A
3112292SN/A    Tick when = curTick() + delay * SimClock::Int::ns;
3123221Sktlim@umich.edu    Tick repeat = period * SimClock::Int::ns;
3133221Sktlim@umich.edu
3143221Sktlim@umich.edu    exitSimLoop("checkpoint", 0, when, repeat);
3152292SN/A}
3162292SN/A
3172292SN/A#if FULL_SYSTEM
3182292SN/A
3192292SN/Auint64_t
3202292SN/Areadfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
3212292SN/A{
3222292SN/A    const string &file = tc->getSystemPtr()->params()->readfile;
3232292SN/A    if (file.empty()) {
3241060SN/A        return ULL(0);
3252292SN/A    }
3261060SN/A
3271060SN/A    uint64_t result = 0;
3282292SN/A
3292292SN/A    int fd = ::open(file.c_str(), O_RDONLY, 0);
3302292SN/A    if (fd < 0)
3312829Sksewell@umich.edu        panic("could not open file %s\n", file);
3322829Sksewell@umich.edu
3333093Sksewell@umich.edu    if (::lseek(fd, offset, SEEK_SET) < 0)
3343093Sksewell@umich.edu        panic("could not seek: %s", strerror(errno));
3353093Sksewell@umich.edu
3363093Sksewell@umich.edu    char *buf = new char[len];
3373093Sksewell@umich.edu    char *p = buf;
3382292SN/A    while (len > 0) {
3391060SN/A        int bytes = ::read(fd, p, len);
3401060SN/A        if (bytes <= 0)
3411060SN/A            break;
3421755SN/A
3431060SN/A        p += bytes;
3441060SN/A        result += bytes;
3451060SN/A        len -= bytes;
3461060SN/A    }
3471060SN/A
3481755SN/A    close(fd);
3491062SN/A    CopyIn(tc, vaddr, buf, result);
3502733Sktlim@umich.edu    delete [] buf;
3512292SN/A    return result;
3522733Sktlim@umich.edu}
3532292SN/A
3542292SN/A#endif
3552292SN/A
3562292SN/Avoid
3572292SN/Adebugbreak(ThreadContext *tc)
3582292SN/A{
3592292SN/A    Debug::breakpoint();
3602292SN/A}
3612292SN/A
3622292SN/Avoid
3632292SN/Aswitchcpu(ThreadContext *tc)
3642292SN/A{
3652292SN/A    exitSimLoop("switchcpu");
3662292SN/A}
3672292SN/A
3682292SN/A//
3692292SN/A// This function is executed when annotated work items begin.  Depending on
3702292SN/A// what the user specified at the command line, the simulation may exit and/or
3712292SN/A// take a checkpoint when a certain work item begins.
3722292SN/A//
3732292SN/Avoid
3742292SN/Aworkbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid)
3752292SN/A{
3762292SN/A    tc->getCpuPtr()->workItemBegin();
3772292SN/A    System *sys = tc->getSystemPtr();
3782292SN/A
3792292SN/A    DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid,
3802292SN/A            threadid);
3812292SN/A
3822292SN/A    //
3832292SN/A    // If specified, determine if this is the specific work item the user
3842292SN/A    // identified
3852292SN/A    //
3862292SN/A    if (sys->params()->work_item_id == -1 ||
3872292SN/A        sys->params()->work_item_id == workid) {
3882292SN/A
3892292SN/A        uint64_t systemWorkBeginCount = sys->incWorkItemsBegin();
3902292SN/A        int cpuId = tc->getCpuPtr()->cpuId();
3912292SN/A
3922292SN/A        if (sys->params()->work_cpus_ckpt_count != 0 &&
3932292SN/A            sys->markWorkItem(cpuId) >= sys->params()->work_cpus_ckpt_count) {
3942292SN/A            //
3952292SN/A            // If active cpus equals checkpoint count, create checkpoint
3962292SN/A            //
3972292SN/A            Event *event = new SimLoopExitEvent("checkpoint", 0);
3982292SN/A            mainEventQueue.schedule(event, curTick());
3992292SN/A        }
4002292SN/A
4012292SN/A        if (systemWorkBeginCount == sys->params()->work_begin_ckpt_count) {
4021062SN/A            //
4031062SN/A            // Note: the string specified as the cause of the exit event must
4041062SN/A            // exactly equal "checkpoint" inorder to create a checkpoint
4052871Sktlim@umich.edu            //
4062871Sktlim@umich.edu            Event *event = new SimLoopExitEvent("checkpoint", 0);
4072871Sktlim@umich.edu            mainEventQueue.schedule(event, curTick());
4082871Sktlim@umich.edu        }
4092871Sktlim@umich.edu
4102871Sktlim@umich.edu        if (systemWorkBeginCount == sys->params()->work_begin_exit_count) {
4112871Sktlim@umich.edu            //
4122871Sktlim@umich.edu            // If a certain number of work items started, exit simulation
4132871Sktlim@umich.edu            //
4142871Sktlim@umich.edu            Event *event = new SimLoopExitEvent("work started count reach", 0);
4152871Sktlim@umich.edu            mainEventQueue.schedule(event, curTick());
4162871Sktlim@umich.edu        }
4171062SN/A
4181755SN/A        if (tc->getCpuPtr()->cpuId() == sys->params()->work_begin_cpu_id_exit) {
4191060SN/A            //
4202733Sktlim@umich.edu            // If work started on the specific cpu id specified, exit simulation
4211060SN/A            //
4222292SN/A            Event *event = new SimLoopExitEvent("work started on specific cpu",
4232292SN/A                                                0);
4242325SN/A
4252292SN/A            mainEventQueue.schedule(event, curTick() + 1);
4262292SN/A        }
4271060SN/A    }
4281060SN/A}
4291060SN/A
4301060SN/A//
4311060SN/A// This function is executed when annotated work items end.  Depending on
4321060SN/A// what the user specified at the command line, the simulation may exit and/or
4331060SN/A// take a checkpoint when a certain work item ends.
4341060SN/A//
4351060SN/Avoid
4361060SN/Aworkend(ThreadContext *tc, uint64_t workid, uint64_t threadid)
4372292SN/A{
4382292SN/A    tc->getCpuPtr()->workItemEnd();
4392292SN/A    System *sys = tc->getSystemPtr();
4402292SN/A
4412292SN/A    DPRINTF(WorkItems, "Work End workid: %d, threadid %d\n", workid, threadid);
4421060SN/A
4431060SN/A    //
4441060SN/A    // If specified, determine if this is the specific work item the user
4451060SN/A    // identified
4461060SN/A    //
4471060SN/A    if (sys->params()->work_item_id == -1 ||
4481060SN/A        sys->params()->work_item_id == workid) {
4492325SN/A
4502292SN/A        uint64_t systemWorkEndCount = sys->incWorkItemsEnd();
4512292SN/A        int cpuId = tc->getCpuPtr()->cpuId();
4522292SN/A
4532292SN/A        if (sys->params()->work_cpus_ckpt_count != 0 &&
4542292SN/A            sys->markWorkItem(cpuId) >= sys->params()->work_cpus_ckpt_count) {
4552325SN/A            //
4562867Sktlim@umich.edu            // If active cpus equals checkpoint count, create checkpoint
4572905Sktlim@umich.edu            //
4583226Sktlim@umich.edu            Event *event = new SimLoopExitEvent("checkpoint", 0);
4592325SN/A            mainEventQueue.schedule(event, curTick());
4602325SN/A        }
4613221Sktlim@umich.edu
4623226Sktlim@umich.edu        if (sys->params()->work_end_ckpt_count != 0 &&
4632325SN/A            systemWorkEndCount == sys->params()->work_end_ckpt_count) {
4642325SN/A            //
4652325SN/A            // If total work items completed equals checkpoint count, create
4662325SN/A            // checkpoint
4673226Sktlim@umich.edu            //
4682325SN/A            Event *event = new SimLoopExitEvent("checkpoint", 0);
4692292SN/A            mainEventQueue.schedule(event, curTick());
4702292SN/A        }
4712292SN/A
4722292SN/A        if (sys->params()->work_end_exit_count != 0 &&
4732292SN/A            systemWorkEndCount == sys->params()->work_end_exit_count) {
4742292SN/A            //
4751060SN/A            // If total work items completed equals exit count, exit simulation
4761060SN/A            //
4771060SN/A            Event *event = new SimLoopExitEvent("work items exit count reached",
4781060SN/A                                                0);
4791755SN/A
4801060SN/A            mainEventQueue.schedule(event, curTick());
4812307SN/A        }
4822680Sktlim@umich.edu    }
4832292SN/A}
4841060SN/A
4852292SN/A} // namespace PseudoInst
4862292SN/A