pc_event.cc revision 1646
14776Sgblack@eecs.umich.edu/*
24776Sgblack@eecs.umich.edu * Copyright (c) 2002-2003 The Regents of The University of Michigan
34776Sgblack@eecs.umich.edu * All rights reserved.
44776Sgblack@eecs.umich.edu *
54776Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
64776Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
74776Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
84776Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
94776Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
104776Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
114776Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
124776Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
134776Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
144776Sgblack@eecs.umich.edu * this software without specific prior written permission.
154776Sgblack@eecs.umich.edu *
164776Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
174776Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
184776Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
194776Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
204776Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
214776Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
224776Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234776Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244776Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254776Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
264776Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274776Sgblack@eecs.umich.edu */
284776Sgblack@eecs.umich.edu
294776Sgblack@eecs.umich.edu#include <algorithm>
304776Sgblack@eecs.umich.edu#include <map>
314776Sgblack@eecs.umich.edu#include <string>
324776Sgblack@eecs.umich.edu#include <utility>
334776Sgblack@eecs.umich.edu
344776Sgblack@eecs.umich.edu#include "base/trace.hh"
354776Sgblack@eecs.umich.edu#include "cpu/base_cpu.hh"
364776Sgblack@eecs.umich.edu#include "cpu/exec_context.hh"
374776Sgblack@eecs.umich.edu#include "cpu/pc_event.hh"
384776Sgblack@eecs.umich.edu#include "sim/debug.hh"
394776Sgblack@eecs.umich.edu#include "sim/universe.hh"
404776Sgblack@eecs.umich.edu
414776Sgblack@eecs.umich.eduusing namespace std;
424776Sgblack@eecs.umich.edu
434776Sgblack@eecs.umich.eduPCEventQueue::PCEventQueue()
444776Sgblack@eecs.umich.edu{}
454776Sgblack@eecs.umich.edu
464776Sgblack@eecs.umich.eduPCEventQueue::~PCEventQueue()
474776Sgblack@eecs.umich.edu{}
484776Sgblack@eecs.umich.edu
494776Sgblack@eecs.umich.edubool
504776Sgblack@eecs.umich.eduPCEventQueue::remove(PCEvent *event)
514776Sgblack@eecs.umich.edu{
524776Sgblack@eecs.umich.edu    int removed = 0;
534776Sgblack@eecs.umich.edu    range_t range = equal_range(event);
544776Sgblack@eecs.umich.edu    for (iterator i = range.first; i != range.second; ++i) {
554776Sgblack@eecs.umich.edu        if (*i == event) {
564776Sgblack@eecs.umich.edu            DPRINTF(PCEvent, "PC based event removed at %#x: %s\n",
574776Sgblack@eecs.umich.edu                    event->pc(), event->descr());
584776Sgblack@eecs.umich.edu            pc_map.erase(i);
594776Sgblack@eecs.umich.edu            ++removed;
604776Sgblack@eecs.umich.edu        }
614776Sgblack@eecs.umich.edu    }
624776Sgblack@eecs.umich.edu
634776Sgblack@eecs.umich.edu    return removed > 0;
644776Sgblack@eecs.umich.edu}
654776Sgblack@eecs.umich.edu
664776Sgblack@eecs.umich.edubool
674776Sgblack@eecs.umich.eduPCEventQueue::schedule(PCEvent *event)
684776Sgblack@eecs.umich.edu{
694776Sgblack@eecs.umich.edu    pc_map.push_back(event);
704776Sgblack@eecs.umich.edu    sort(pc_map.begin(), pc_map.end(), MapCompare());
714776Sgblack@eecs.umich.edu
724776Sgblack@eecs.umich.edu    DPRINTF(PCEvent, "PC based event scheduled for %#x: %s\n",
734776Sgblack@eecs.umich.edu            event->pc(), event->descr());
744776Sgblack@eecs.umich.edu
754776Sgblack@eecs.umich.edu    return true;
764776Sgblack@eecs.umich.edu}
774776Sgblack@eecs.umich.edu
784776Sgblack@eecs.umich.edubool
794776Sgblack@eecs.umich.eduPCEventQueue::doService(ExecContext *xc)
804776Sgblack@eecs.umich.edu{
814776Sgblack@eecs.umich.edu    Addr pc = xc->regs.pc & ~0x3;
824776Sgblack@eecs.umich.edu    int serviced = 0;
834776Sgblack@eecs.umich.edu    range_t range = equal_range(pc);
844776Sgblack@eecs.umich.edu    for (iterator i = range.first; i != range.second; ++i) {
85        // Make sure that the pc wasn't changed as the side effect of
86        // another event.  This for example, prevents two invocations
87        // of the SkipFuncEvent.  Maybe we should have separate PC
88        // event queues for each processor?
89        if (pc != (xc->regs.pc & ~0x3))
90            continue;
91
92        DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
93                (*i)->pc(), (*i)->descr());
94
95        (*i)->process(xc);
96        ++serviced;
97    }
98
99    return serviced > 0;
100}
101
102void
103PCEventQueue::dump() const
104{
105    const_iterator i = pc_map.begin();
106    const_iterator e = pc_map.end();
107
108    for (; i != e; ++i)
109        cprintf("%d: event at %#x: %s\n", curTick, (*i)->pc(),
110                (*i)->descr());
111}
112
113PCEventQueue::range_t
114PCEventQueue::equal_range(Addr pc)
115{
116    return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare());
117}
118
119BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del)
120    : PCEvent(q, desc), remove(del)
121{
122}
123
124void
125BreakPCEvent::process(ExecContext *xc)
126{
127    StringWrap name(xc->cpu->name() + ".break_event");
128    DPRINTFN("break event %s triggered\n", descr());
129    debug_break();
130    if (remove)
131        delete this;
132}
133
134#ifdef FULL_SYSTEM
135extern "C"
136void
137sched_break_pc_sys(System *sys, Addr addr)
138{
139    PCEvent *event = new BreakPCEvent(&sys->pcEventQueue, "debug break", true);
140    event->schedule(addr);
141}
142
143extern "C"
144void
145sched_break_pc(Addr addr)
146{
147     for (vector<System *>::iterator sysi = System::systemList.begin();
148          sysi != System::systemList.end(); ++sysi) {
149         sched_break_pc_sys(*sysi, addr);
150    }
151
152}
153#endif
154