pseudo_inst.cc revision 4437:b6e304245729
110802Srene.dejong@arm.com/*
210802Srene.dejong@arm.com * Copyright (c) 2003-2006 The Regents of The University of Michigan
310802Srene.dejong@arm.com * All rights reserved.
410802Srene.dejong@arm.com *
510802Srene.dejong@arm.com * Redistribution and use in source and binary forms, with or without
610802Srene.dejong@arm.com * modification, are permitted provided that the following conditions are
710802Srene.dejong@arm.com * met: redistributions of source code must retain the above copyright
810802Srene.dejong@arm.com * notice, this list of conditions and the following disclaimer;
910802Srene.dejong@arm.com * redistributions in binary form must reproduce the above copyright
1010802Srene.dejong@arm.com * notice, this list of conditions and the following disclaimer in the
1110802Srene.dejong@arm.com * documentation and/or other materials provided with the distribution;
1210802Srene.dejong@arm.com * neither the name of the copyright holders nor the names of its
1310802Srene.dejong@arm.com * contributors may be used to endorse or promote products derived from
1410802Srene.dejong@arm.com * this software without specific prior written permission.
1510802Srene.dejong@arm.com *
1610802Srene.dejong@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710802Srene.dejong@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810802Srene.dejong@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910802Srene.dejong@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010802Srene.dejong@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110802Srene.dejong@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210802Srene.dejong@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310802Srene.dejong@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410802Srene.dejong@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510802Srene.dejong@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610802Srene.dejong@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710802Srene.dejong@arm.com *
2810802Srene.dejong@arm.com * Authors: Nathan Binkert
2910802Srene.dejong@arm.com */
3010802Srene.dejong@arm.com
3110802Srene.dejong@arm.com#include <errno.h>
3210802Srene.dejong@arm.com#include <fcntl.h>
3310802Srene.dejong@arm.com#include <unistd.h>
3410802Srene.dejong@arm.com
3510802Srene.dejong@arm.com#include <fstream>
3610802Srene.dejong@arm.com#include <string>
3710802Srene.dejong@arm.com
3810802Srene.dejong@arm.com#include "arch/vtophys.hh"
3910802Srene.dejong@arm.com#include "base/annotate.hh"
4010802Srene.dejong@arm.com#include "cpu/base.hh"
4110802Srene.dejong@arm.com#include "cpu/thread_context.hh"
4210802Srene.dejong@arm.com#include "cpu/quiesce_event.hh"
4310802Srene.dejong@arm.com#include "arch/kernel_stats.hh"
4410802Srene.dejong@arm.com#include "sim/pseudo_inst.hh"
4510802Srene.dejong@arm.com#include "sim/serialize.hh"
4610802Srene.dejong@arm.com#include "sim/sim_exit.hh"
4710802Srene.dejong@arm.com#include "sim/stat_control.hh"
4810802Srene.dejong@arm.com#include "sim/stats.hh"
4910802Srene.dejong@arm.com#include "sim/system.hh"
5010802Srene.dejong@arm.com#include "sim/debug.hh"
5110802Srene.dejong@arm.com#include "sim/vptr.hh"
5210802Srene.dejong@arm.com
5310802Srene.dejong@arm.comusing namespace std;
5410802Srene.dejong@arm.com
5510802Srene.dejong@arm.comusing namespace Stats;
5610802Srene.dejong@arm.comusing namespace TheISA;
5710802Srene.dejong@arm.com
5810802Srene.dejong@arm.comnamespace PseudoInst
5910802Srene.dejong@arm.com{
6010802Srene.dejong@arm.com    void
6110802Srene.dejong@arm.com    arm(ThreadContext *tc)
6210802Srene.dejong@arm.com    {
6310802Srene.dejong@arm.com        if (tc->getKernelStats())
6410802Srene.dejong@arm.com            tc->getKernelStats()->arm();
6510802Srene.dejong@arm.com    }
6610802Srene.dejong@arm.com
6710802Srene.dejong@arm.com    void
6810802Srene.dejong@arm.com    quiesce(ThreadContext *tc)
6910802Srene.dejong@arm.com    {
7010802Srene.dejong@arm.com        if (!tc->getCpuPtr()->params->do_quiesce)
7110802Srene.dejong@arm.com            return;
7210802Srene.dejong@arm.com
7310802Srene.dejong@arm.com        DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
7410802Srene.dejong@arm.com
7510802Srene.dejong@arm.com        tc->suspend();
7610802Srene.dejong@arm.com        if (tc->getKernelStats())
7710802Srene.dejong@arm.com            tc->getKernelStats()->quiesce();
7810802Srene.dejong@arm.com    }
7910802Srene.dejong@arm.com
8010802Srene.dejong@arm.com    void
8110802Srene.dejong@arm.com    quiesceNs(ThreadContext *tc, uint64_t ns)
8210802Srene.dejong@arm.com    {
8310802Srene.dejong@arm.com        if (!tc->getCpuPtr()->params->do_quiesce || ns == 0)
8410802Srene.dejong@arm.com            return;
8510802Srene.dejong@arm.com
8610802Srene.dejong@arm.com        EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
8710802Srene.dejong@arm.com
8810802Srene.dejong@arm.com        Tick resume = curTick + Clock::Int::ns * ns;
8910802Srene.dejong@arm.com
9010802Srene.dejong@arm.com        quiesceEvent->reschedule(resume, true);
9110802Srene.dejong@arm.com
9210802Srene.dejong@arm.com        DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
9310802Srene.dejong@arm.com                tc->getCpuPtr()->name(), ns, resume);
9410802Srene.dejong@arm.com
9510802Srene.dejong@arm.com        tc->suspend();
9610802Srene.dejong@arm.com        if (tc->getKernelStats())
9710802Srene.dejong@arm.com            tc->getKernelStats()->quiesce();
9810802Srene.dejong@arm.com    }
9910802Srene.dejong@arm.com
10010802Srene.dejong@arm.com    void
10110802Srene.dejong@arm.com    quiesceCycles(ThreadContext *tc, uint64_t cycles)
10210802Srene.dejong@arm.com    {
10310802Srene.dejong@arm.com        if (!tc->getCpuPtr()->params->do_quiesce || cycles == 0)
10410802Srene.dejong@arm.com            return;
10510802Srene.dejong@arm.com
10610802Srene.dejong@arm.com        EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
10710802Srene.dejong@arm.com
10810802Srene.dejong@arm.com        Tick resume = curTick + tc->getCpuPtr()->cycles(cycles);
10910802Srene.dejong@arm.com
11010802Srene.dejong@arm.com        quiesceEvent->reschedule(resume, true);
11110802Srene.dejong@arm.com
11210802Srene.dejong@arm.com        DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
11310802Srene.dejong@arm.com                tc->getCpuPtr()->name(), cycles, resume);
11410802Srene.dejong@arm.com
11510802Srene.dejong@arm.com        tc->suspend();
11610802Srene.dejong@arm.com        if (tc->getKernelStats())
11710802Srene.dejong@arm.com            tc->getKernelStats()->quiesce();
11810802Srene.dejong@arm.com    }
11910802Srene.dejong@arm.com
12010802Srene.dejong@arm.com    uint64_t
12110802Srene.dejong@arm.com    quiesceTime(ThreadContext *tc)
12210802Srene.dejong@arm.com    {
12310802Srene.dejong@arm.com        return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns;
12410802Srene.dejong@arm.com    }
12510802Srene.dejong@arm.com
12610802Srene.dejong@arm.com    void
12710802Srene.dejong@arm.com    m5exit_old(ThreadContext *tc)
12810802Srene.dejong@arm.com    {
12910802Srene.dejong@arm.com        exitSimLoop("m5_exit_old instruction encountered");
13010802Srene.dejong@arm.com    }
13110802Srene.dejong@arm.com
13210802Srene.dejong@arm.com    void
13310802Srene.dejong@arm.com    m5exit(ThreadContext *tc, Tick delay)
13410802Srene.dejong@arm.com    {
13510802Srene.dejong@arm.com        Tick when = curTick + delay * Clock::Int::ns;
13610802Srene.dejong@arm.com        schedExitSimLoop("m5_exit instruction encountered", when);
13710802Srene.dejong@arm.com    }
13810802Srene.dejong@arm.com
13910802Srene.dejong@arm.com    void
14010802Srene.dejong@arm.com    loadsymbol(ThreadContext *tc)
14110802Srene.dejong@arm.com    {
14210802Srene.dejong@arm.com        const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
14310802Srene.dejong@arm.com        if (filename.empty()) {
14410802Srene.dejong@arm.com            return;
14510802Srene.dejong@arm.com        }
14610802Srene.dejong@arm.com
14710802Srene.dejong@arm.com        std::string buffer;
14810802Srene.dejong@arm.com        ifstream file(filename.c_str());
14910802Srene.dejong@arm.com
15010802Srene.dejong@arm.com        if (!file)
15110802Srene.dejong@arm.com            fatal("file error: Can't open symbol table file %s\n", filename);
15210802Srene.dejong@arm.com
15310802Srene.dejong@arm.com        while (!file.eof()) {
15410802Srene.dejong@arm.com            getline(file, buffer);
15511264Sandreas.sandberg@arm.com
15610802Srene.dejong@arm.com            if (buffer.empty())
15710802Srene.dejong@arm.com                continue;
15810802Srene.dejong@arm.com
15910802Srene.dejong@arm.com            int idx = buffer.find(' ');
16010802Srene.dejong@arm.com            if (idx == string::npos)
16110802Srene.dejong@arm.com                continue;
16210802Srene.dejong@arm.com
16310802Srene.dejong@arm.com            string address = "0x" + buffer.substr(0, idx);
16410802Srene.dejong@arm.com            eat_white(address);
16510802Srene.dejong@arm.com            if (address.empty())
16610802Srene.dejong@arm.com                continue;
16710802Srene.dejong@arm.com
16810802Srene.dejong@arm.com            // Skip over letter and space
16910802Srene.dejong@arm.com            string symbol = buffer.substr(idx + 3);
17010802Srene.dejong@arm.com            eat_white(symbol);
17110802Srene.dejong@arm.com            if (symbol.empty())
17210802Srene.dejong@arm.com                continue;
17310802Srene.dejong@arm.com
17410802Srene.dejong@arm.com            Addr addr;
17510802Srene.dejong@arm.com            if (!to_number(address, addr))
17611168Sandreas.hansson@arm.com                continue;
17710802Srene.dejong@arm.com
17811168Sandreas.hansson@arm.com            if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
17911168Sandreas.hansson@arm.com                continue;
18010802Srene.dejong@arm.com
18110802Srene.dejong@arm.com
18210802Srene.dejong@arm.com            DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
18310802Srene.dejong@arm.com        }
18410802Srene.dejong@arm.com        file.close();
18510802Srene.dejong@arm.com    }
18610802Srene.dejong@arm.com
18710802Srene.dejong@arm.com    void
18810802Srene.dejong@arm.com    resetstats(ThreadContext *tc, Tick delay, Tick period)
18910802Srene.dejong@arm.com    {
19010802Srene.dejong@arm.com        if (!tc->getCpuPtr()->params->do_statistics_insts)
19110802Srene.dejong@arm.com            return;
19210802Srene.dejong@arm.com
19310802Srene.dejong@arm.com
19410802Srene.dejong@arm.com        Tick when = curTick + delay * Clock::Int::ns;
19510802Srene.dejong@arm.com        Tick repeat = period * Clock::Int::ns;
19610802Srene.dejong@arm.com
19710802Srene.dejong@arm.com        Stats::StatEvent(false, true, when, repeat);
19810802Srene.dejong@arm.com    }
19910802Srene.dejong@arm.com
20010802Srene.dejong@arm.com    void
20110802Srene.dejong@arm.com    dumpstats(ThreadContext *tc, Tick delay, Tick period)
20210802Srene.dejong@arm.com    {
20310802Srene.dejong@arm.com        if (!tc->getCpuPtr()->params->do_statistics_insts)
20410802Srene.dejong@arm.com            return;
20510802Srene.dejong@arm.com
20610802Srene.dejong@arm.com
20710802Srene.dejong@arm.com        Tick when = curTick + delay * Clock::Int::ns;
20810802Srene.dejong@arm.com        Tick repeat = period * Clock::Int::ns;
20910802Srene.dejong@arm.com
21010802Srene.dejong@arm.com        Stats::StatEvent(true, false, when, repeat);
21110802Srene.dejong@arm.com    }
21210802Srene.dejong@arm.com
21310802Srene.dejong@arm.com    void
21410802Srene.dejong@arm.com    addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
21510802Srene.dejong@arm.com    {
21610802Srene.dejong@arm.com        char symb[100];
21710802Srene.dejong@arm.com        CopyStringOut(tc, symb, symbolAddr, 100);
21810802Srene.dejong@arm.com        std::string symbol(symb);
21910802Srene.dejong@arm.com
22010802Srene.dejong@arm.com        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
22110802Srene.dejong@arm.com
22210802Srene.dejong@arm.com        tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
22310802Srene.dejong@arm.com    }
22410802Srene.dejong@arm.com
22510802Srene.dejong@arm.com    void
22610802Srene.dejong@arm.com    anBegin(ThreadContext *tc, uint64_t cur)
22710802Srene.dejong@arm.com    {
22810802Srene.dejong@arm.com        Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur &
22910802Srene.dejong@arm.com                0xFFFFFFFF, 0,0);
23010802Srene.dejong@arm.com    }
23110802Srene.dejong@arm.com
23210802Srene.dejong@arm.com    void
23310802Srene.dejong@arm.com    anWait(ThreadContext *tc, uint64_t cur, uint64_t wait)
23410802Srene.dejong@arm.com    {
23510802Srene.dejong@arm.com        Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur &
23610802Srene.dejong@arm.com                0xFFFFFFFF, wait >> 32, wait & 0xFFFFFFFF);
23710802Srene.dejong@arm.com    }
23810802Srene.dejong@arm.com
23910802Srene.dejong@arm.com
24010802Srene.dejong@arm.com    void
24110802Srene.dejong@arm.com    dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
24210802Srene.dejong@arm.com    {
24310802Srene.dejong@arm.com        if (!tc->getCpuPtr()->params->do_statistics_insts)
24410802Srene.dejong@arm.com            return;
24510802Srene.dejong@arm.com
24610802Srene.dejong@arm.com
24710802Srene.dejong@arm.com        Tick when = curTick + delay * Clock::Int::ns;
24810802Srene.dejong@arm.com        Tick repeat = period * Clock::Int::ns;
24910802Srene.dejong@arm.com
25010802Srene.dejong@arm.com        Stats::StatEvent(true, true, when, repeat);
25110802Srene.dejong@arm.com    }
25210802Srene.dejong@arm.com
25310802Srene.dejong@arm.com    void
25410802Srene.dejong@arm.com    m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
25510802Srene.dejong@arm.com    {
25610802Srene.dejong@arm.com        if (!tc->getCpuPtr()->params->do_checkpoint_insts)
25710802Srene.dejong@arm.com            return;
25810802Srene.dejong@arm.com
25910802Srene.dejong@arm.com        Tick when = curTick + delay * Clock::Int::ns;
26010802Srene.dejong@arm.com        Tick repeat = period * Clock::Int::ns;
26110802Srene.dejong@arm.com
26210802Srene.dejong@arm.com        schedExitSimLoop("checkpoint", when, repeat);
26310802Srene.dejong@arm.com    }
26410802Srene.dejong@arm.com
26510802Srene.dejong@arm.com    uint64_t
26610802Srene.dejong@arm.com    readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
26710802Srene.dejong@arm.com    {
26810802Srene.dejong@arm.com        const string &file = tc->getSystemPtr()->params()->readfile;
26910802Srene.dejong@arm.com        if (file.empty()) {
27010802Srene.dejong@arm.com            return ULL(0);
27110802Srene.dejong@arm.com        }
27210802Srene.dejong@arm.com
27310802Srene.dejong@arm.com        uint64_t result = 0;
27410802Srene.dejong@arm.com
27510802Srene.dejong@arm.com        int fd = ::open(file.c_str(), O_RDONLY, 0);
27610802Srene.dejong@arm.com        if (fd < 0)
27710802Srene.dejong@arm.com            panic("could not open file %s\n", file);
27810802Srene.dejong@arm.com
27910802Srene.dejong@arm.com        if (::lseek(fd, offset, SEEK_SET) < 0)
28010802Srene.dejong@arm.com            panic("could not seek: %s", strerror(errno));
28110802Srene.dejong@arm.com
28210802Srene.dejong@arm.com        char *buf = new char[len];
28310802Srene.dejong@arm.com        char *p = buf;
28410802Srene.dejong@arm.com        while (len > 0) {
28510802Srene.dejong@arm.com            int bytes = ::read(fd, p, len);
28610802Srene.dejong@arm.com            if (bytes <= 0)
28710802Srene.dejong@arm.com                break;
28810802Srene.dejong@arm.com
28910802Srene.dejong@arm.com            p += bytes;
29010802Srene.dejong@arm.com            result += bytes;
29110802Srene.dejong@arm.com            len -= bytes;
29210802Srene.dejong@arm.com        }
29310802Srene.dejong@arm.com
29410802Srene.dejong@arm.com        close(fd);
29510802Srene.dejong@arm.com        CopyIn(tc, vaddr, buf, result);
29610802Srene.dejong@arm.com        delete [] buf;
29710802Srene.dejong@arm.com        return result;
29810802Srene.dejong@arm.com    }
29910802Srene.dejong@arm.com
30010802Srene.dejong@arm.com    void debugbreak(ThreadContext *tc)
30110802Srene.dejong@arm.com    {
30210802Srene.dejong@arm.com        debug_break();
30310802Srene.dejong@arm.com    }
30410802Srene.dejong@arm.com
30510802Srene.dejong@arm.com    void switchcpu(ThreadContext *tc)
30610802Srene.dejong@arm.com    {
30710802Srene.dejong@arm.com        exitSimLoop("switchcpu");
30810802Srene.dejong@arm.com    }
30910802Srene.dejong@arm.com}
31010802Srene.dejong@arm.com