ua2005.cc (5531:a5ff5e57fafd) ua2005.cc (5606:6da7a58b0bc8)
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "arch/sparc/kernel_stats.hh"
30#include "arch/sparc/miscregfile.hh"
31#include "base/bitfield.hh"
32#include "base/trace.hh"
33#include "cpu/base.hh"
34#include "cpu/thread_context.hh"
35#include "sim/system.hh"
36
37using namespace SparcISA;
38
39
40void
41MiscRegFile::checkSoftInt(ThreadContext *tc)
42{
43 BaseCPU *cpu = tc->getCpuPtr();
44
45 // If PIL < 14, copy over the tm and sm bits
46 if (pil < 14 && softint & 0x10000)
47 cpu->post_interrupt(IT_SOFT_INT, 16);
48 else
49 cpu->clear_interrupt(IT_SOFT_INT, 16);
50 if (pil < 14 && softint & 0x1)
51 cpu->post_interrupt(IT_SOFT_INT, 0);
52 else
53 cpu->clear_interrupt(IT_SOFT_INT, 0);
54
55 // Copy over any of the other bits that are set
56 for (int bit = 15; bit > 0; --bit) {
57 if (1 << bit & softint && bit > pil)
58 cpu->post_interrupt(IT_SOFT_INT, bit);
59 else
60 cpu->clear_interrupt(IT_SOFT_INT, bit);
61 }
62}
63
64
65void
66MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
67{
68 BaseCPU *cpu = tc->getCpuPtr();
69
70 int64_t time;
71 switch (miscReg) {
72 /* Full system only ASRs */
73 case MISCREG_SOFTINT:
74 setRegNoEffect(miscReg, val);;
75 checkSoftInt(tc);
76 break;
77 case MISCREG_SOFTINT_CLR:
78 return setReg(MISCREG_SOFTINT, ~val & softint, tc);
79 case MISCREG_SOFTINT_SET:
80 return setReg(MISCREG_SOFTINT, val | softint, tc);
81
82 case MISCREG_TICK_CMPR:
83 if (tickCompare == NULL)
84 tickCompare = new TickCompareEvent(this, tc);
85 setRegNoEffect(miscReg, val);
86 if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled())
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "arch/sparc/kernel_stats.hh"
30#include "arch/sparc/miscregfile.hh"
31#include "base/bitfield.hh"
32#include "base/trace.hh"
33#include "cpu/base.hh"
34#include "cpu/thread_context.hh"
35#include "sim/system.hh"
36
37using namespace SparcISA;
38
39
40void
41MiscRegFile::checkSoftInt(ThreadContext *tc)
42{
43 BaseCPU *cpu = tc->getCpuPtr();
44
45 // If PIL < 14, copy over the tm and sm bits
46 if (pil < 14 && softint & 0x10000)
47 cpu->post_interrupt(IT_SOFT_INT, 16);
48 else
49 cpu->clear_interrupt(IT_SOFT_INT, 16);
50 if (pil < 14 && softint & 0x1)
51 cpu->post_interrupt(IT_SOFT_INT, 0);
52 else
53 cpu->clear_interrupt(IT_SOFT_INT, 0);
54
55 // Copy over any of the other bits that are set
56 for (int bit = 15; bit > 0; --bit) {
57 if (1 << bit & softint && bit > pil)
58 cpu->post_interrupt(IT_SOFT_INT, bit);
59 else
60 cpu->clear_interrupt(IT_SOFT_INT, bit);
61 }
62}
63
64
65void
66MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
67{
68 BaseCPU *cpu = tc->getCpuPtr();
69
70 int64_t time;
71 switch (miscReg) {
72 /* Full system only ASRs */
73 case MISCREG_SOFTINT:
74 setRegNoEffect(miscReg, val);;
75 checkSoftInt(tc);
76 break;
77 case MISCREG_SOFTINT_CLR:
78 return setReg(MISCREG_SOFTINT, ~val & softint, tc);
79 case MISCREG_SOFTINT_SET:
80 return setReg(MISCREG_SOFTINT, val | softint, tc);
81
82 case MISCREG_TICK_CMPR:
83 if (tickCompare == NULL)
84 tickCompare = new TickCompareEvent(this, tc);
85 setRegNoEffect(miscReg, val);
86 if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled())
87 tickCompare->deschedule();
87 cpu->deschedule(tickCompare);
88 time = (tick_cmpr & mask(63)) - (tick & mask(63));
89 if (!(tick_cmpr & ~mask(63)) && time > 0) {
90 if (tickCompare->scheduled())
88 time = (tick_cmpr & mask(63)) - (tick & mask(63));
89 if (!(tick_cmpr & ~mask(63)) && time > 0) {
90 if (tickCompare->scheduled())
91 tickCompare->deschedule();
92 tickCompare->schedule(time * cpu->ticks(1));
91 cpu->deschedule(tickCompare);
92 cpu->schedule(tickCompare, curTick + time * cpu->ticks(1));
93 }
94 panic("writing to TICK compare register %#X\n", val);
95 break;
96
97 case MISCREG_STICK_CMPR:
98 if (sTickCompare == NULL)
99 sTickCompare = new STickCompareEvent(this, tc);
100 setRegNoEffect(miscReg, val);
101 if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
93 }
94 panic("writing to TICK compare register %#X\n", val);
95 break;
96
97 case MISCREG_STICK_CMPR:
98 if (sTickCompare == NULL)
99 sTickCompare = new STickCompareEvent(this, tc);
100 setRegNoEffect(miscReg, val);
101 if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
102 sTickCompare->deschedule();
102 cpu->deschedule(sTickCompare);
103 time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
104 cpu->instCount();
105 if (!(stick_cmpr & ~mask(63)) && time > 0) {
106 if (sTickCompare->scheduled())
103 time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
104 cpu->instCount();
105 if (!(stick_cmpr & ~mask(63)) && time > 0) {
106 if (sTickCompare->scheduled())
107 sTickCompare->deschedule();
108 sTickCompare->schedule(time * cpu->ticks(1) + curTick);
107 cpu->deschedule(sTickCompare);
108 cpu->schedule(sTickCompare, curTick + time * cpu->ticks(1));
109 }
110 DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
111 break;
112
113 case MISCREG_PSTATE:
114 setRegNoEffect(miscReg, val);
115
116 case MISCREG_PIL:
117 setRegNoEffect(miscReg, val);
118 checkSoftInt(tc);
119 break;
120
121 case MISCREG_HVER:
122 panic("Shouldn't be writing HVER\n");
123
124 case MISCREG_HINTP:
125 setRegNoEffect(miscReg, val);
126 if (hintp)
127 cpu->post_interrupt(IT_HINTP, 0);
128 else
129 cpu->clear_interrupt(IT_HINTP, 0);
130 break;
131
132 case MISCREG_HTBA:
133 // clear lower 7 bits on writes.
134 setRegNoEffect(miscReg, val & ULL(~0x7FFF));
135 break;
136
137 case MISCREG_QUEUE_CPU_MONDO_HEAD:
138 case MISCREG_QUEUE_CPU_MONDO_TAIL:
139 setRegNoEffect(miscReg, val);
140 if (cpu_mondo_head != cpu_mondo_tail)
141 cpu->post_interrupt(IT_CPU_MONDO, 0);
142 else
143 cpu->clear_interrupt(IT_CPU_MONDO, 0);
144 break;
145 case MISCREG_QUEUE_DEV_MONDO_HEAD:
146 case MISCREG_QUEUE_DEV_MONDO_TAIL:
147 setRegNoEffect(miscReg, val);
148 if (dev_mondo_head != dev_mondo_tail)
149 cpu->post_interrupt(IT_DEV_MONDO, 0);
150 else
151 cpu->clear_interrupt(IT_DEV_MONDO, 0);
152 break;
153 case MISCREG_QUEUE_RES_ERROR_HEAD:
154 case MISCREG_QUEUE_RES_ERROR_TAIL:
155 setRegNoEffect(miscReg, val);
156 if (res_error_head != res_error_tail)
157 cpu->post_interrupt(IT_RES_ERROR, 0);
158 else
159 cpu->clear_interrupt(IT_RES_ERROR, 0);
160 break;
161 case MISCREG_QUEUE_NRES_ERROR_HEAD:
162 case MISCREG_QUEUE_NRES_ERROR_TAIL:
163 setRegNoEffect(miscReg, val);
164 // This one doesn't have an interrupt to report to the guest OS
165 break;
166
167 case MISCREG_HSTICK_CMPR:
168 if (hSTickCompare == NULL)
169 hSTickCompare = new HSTickCompareEvent(this, tc);
170 setRegNoEffect(miscReg, val);
171 if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
109 }
110 DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
111 break;
112
113 case MISCREG_PSTATE:
114 setRegNoEffect(miscReg, val);
115
116 case MISCREG_PIL:
117 setRegNoEffect(miscReg, val);
118 checkSoftInt(tc);
119 break;
120
121 case MISCREG_HVER:
122 panic("Shouldn't be writing HVER\n");
123
124 case MISCREG_HINTP:
125 setRegNoEffect(miscReg, val);
126 if (hintp)
127 cpu->post_interrupt(IT_HINTP, 0);
128 else
129 cpu->clear_interrupt(IT_HINTP, 0);
130 break;
131
132 case MISCREG_HTBA:
133 // clear lower 7 bits on writes.
134 setRegNoEffect(miscReg, val & ULL(~0x7FFF));
135 break;
136
137 case MISCREG_QUEUE_CPU_MONDO_HEAD:
138 case MISCREG_QUEUE_CPU_MONDO_TAIL:
139 setRegNoEffect(miscReg, val);
140 if (cpu_mondo_head != cpu_mondo_tail)
141 cpu->post_interrupt(IT_CPU_MONDO, 0);
142 else
143 cpu->clear_interrupt(IT_CPU_MONDO, 0);
144 break;
145 case MISCREG_QUEUE_DEV_MONDO_HEAD:
146 case MISCREG_QUEUE_DEV_MONDO_TAIL:
147 setRegNoEffect(miscReg, val);
148 if (dev_mondo_head != dev_mondo_tail)
149 cpu->post_interrupt(IT_DEV_MONDO, 0);
150 else
151 cpu->clear_interrupt(IT_DEV_MONDO, 0);
152 break;
153 case MISCREG_QUEUE_RES_ERROR_HEAD:
154 case MISCREG_QUEUE_RES_ERROR_TAIL:
155 setRegNoEffect(miscReg, val);
156 if (res_error_head != res_error_tail)
157 cpu->post_interrupt(IT_RES_ERROR, 0);
158 else
159 cpu->clear_interrupt(IT_RES_ERROR, 0);
160 break;
161 case MISCREG_QUEUE_NRES_ERROR_HEAD:
162 case MISCREG_QUEUE_NRES_ERROR_TAIL:
163 setRegNoEffect(miscReg, val);
164 // This one doesn't have an interrupt to report to the guest OS
165 break;
166
167 case MISCREG_HSTICK_CMPR:
168 if (hSTickCompare == NULL)
169 hSTickCompare = new HSTickCompareEvent(this, tc);
170 setRegNoEffect(miscReg, val);
171 if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
172 hSTickCompare->deschedule();
172 cpu->deschedule(hSTickCompare);
173 time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
174 cpu->instCount();
175 if (!(hstick_cmpr & ~mask(63)) && time > 0) {
176 if (hSTickCompare->scheduled())
173 time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
174 cpu->instCount();
175 if (!(hstick_cmpr & ~mask(63)) && time > 0) {
176 if (hSTickCompare->scheduled())
177 hSTickCompare->deschedule();
178 hSTickCompare->schedule(curTick + time * cpu->ticks(1));
177 cpu->deschedule(hSTickCompare);
178 cpu->schedule(hSTickCompare, curTick + time * cpu->ticks(1));
179 }
180 DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
181 break;
182
183 case MISCREG_HPSTATE:
184 // T1000 spec says impl. dependent val must always be 1
185 setRegNoEffect(miscReg, val | HPSTATE::id);
186#if FULL_SYSTEM
187 if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv))
188 cpu->post_interrupt(IT_TRAP_LEVEL_ZERO, 0);
189 else
190 cpu->clear_interrupt(IT_TRAP_LEVEL_ZERO, 0);
191#endif
192 break;
193 case MISCREG_HTSTATE:
194 setRegNoEffect(miscReg, val);
195 break;
196
197 case MISCREG_STRAND_STS_REG:
198 if (bits(val,2,2))
199 panic("No support for setting spec_en bit\n");
200 setRegNoEffect(miscReg, bits(val,0,0));
201 if (!bits(val,0,0)) {
202 DPRINTF(Quiesce, "Cpu executed quiescing instruction\n");
203 // Time to go to sleep
204 tc->suspend();
205 if (tc->getKernelStats())
206 tc->getKernelStats()->quiesce();
207 }
208 break;
209
210 default:
211 panic("Invalid write to FS misc register %s\n",
212 getMiscRegName(miscReg));
213 }
214}
215
216MiscReg
217MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
218{
219 uint64_t temp;
220
221 switch (miscReg) {
222 /* Privileged registers. */
223 case MISCREG_QUEUE_CPU_MONDO_HEAD:
224 case MISCREG_QUEUE_CPU_MONDO_TAIL:
225 case MISCREG_QUEUE_DEV_MONDO_HEAD:
226 case MISCREG_QUEUE_DEV_MONDO_TAIL:
227 case MISCREG_QUEUE_RES_ERROR_HEAD:
228 case MISCREG_QUEUE_RES_ERROR_TAIL:
229 case MISCREG_QUEUE_NRES_ERROR_HEAD:
230 case MISCREG_QUEUE_NRES_ERROR_TAIL:
231 case MISCREG_SOFTINT:
232 case MISCREG_TICK_CMPR:
233 case MISCREG_STICK_CMPR:
234 case MISCREG_PIL:
235 case MISCREG_HPSTATE:
236 case MISCREG_HINTP:
237 case MISCREG_HTSTATE:
238 case MISCREG_HSTICK_CMPR:
239 return readRegNoEffect(miscReg) ;
240
241 case MISCREG_HTBA:
242 return readRegNoEffect(miscReg) & ULL(~0x7FFF);
243 case MISCREG_HVER:
244 // XXX set to match Legion
245 return ULL(0x3e) << 48 |
246 ULL(0x23) << 32 |
247 ULL(0x20) << 24 |
248 //MaxGL << 16 | XXX For some reason legion doesn't set GL
249 MaxTL << 8 |
250 (NWindows -1) << 0;
251
252 case MISCREG_STRAND_STS_REG:
253 System *sys;
254 int x;
255 sys = tc->getSystemPtr();
256
257 temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative);
258 // Check that the CPU array is fully populated
259 // (by calling getNumCPus())
260 assert(sys->getNumCPUs() > tc->readCpuId());
261
262 temp |= tc->readCpuId() << STS::shft_id;
263
264 for (x = tc->readCpuId() & ~3; x < sys->threadContexts.size(); x++) {
265 switch (sys->threadContexts[x]->status()) {
266 case ThreadContext::Active:
267 temp |= STS::st_run << (STS::shft_fsm0 -
268 ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
269 break;
270 case ThreadContext::Suspended:
271 // should this be idle?
272 temp |= STS::st_idle << (STS::shft_fsm0 -
273 ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
274 break;
275 case ThreadContext::Halted:
276 temp |= STS::st_halt << (STS::shft_fsm0 -
277 ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
278 break;
279 default:
280 panic("What state are we in?!\n");
281 } // switch
282 } // for
283
284 return temp;
285 default:
286 panic("Invalid read to FS misc register\n");
287 }
288}
289
290void
291MiscRegFile::processTickCompare(ThreadContext *tc)
292{
293 panic("tick compare not implemented\n");
294}
295
296void
297MiscRegFile::processSTickCompare(ThreadContext *tc)
298{
179 }
180 DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
181 break;
182
183 case MISCREG_HPSTATE:
184 // T1000 spec says impl. dependent val must always be 1
185 setRegNoEffect(miscReg, val | HPSTATE::id);
186#if FULL_SYSTEM
187 if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv))
188 cpu->post_interrupt(IT_TRAP_LEVEL_ZERO, 0);
189 else
190 cpu->clear_interrupt(IT_TRAP_LEVEL_ZERO, 0);
191#endif
192 break;
193 case MISCREG_HTSTATE:
194 setRegNoEffect(miscReg, val);
195 break;
196
197 case MISCREG_STRAND_STS_REG:
198 if (bits(val,2,2))
199 panic("No support for setting spec_en bit\n");
200 setRegNoEffect(miscReg, bits(val,0,0));
201 if (!bits(val,0,0)) {
202 DPRINTF(Quiesce, "Cpu executed quiescing instruction\n");
203 // Time to go to sleep
204 tc->suspend();
205 if (tc->getKernelStats())
206 tc->getKernelStats()->quiesce();
207 }
208 break;
209
210 default:
211 panic("Invalid write to FS misc register %s\n",
212 getMiscRegName(miscReg));
213 }
214}
215
216MiscReg
217MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
218{
219 uint64_t temp;
220
221 switch (miscReg) {
222 /* Privileged registers. */
223 case MISCREG_QUEUE_CPU_MONDO_HEAD:
224 case MISCREG_QUEUE_CPU_MONDO_TAIL:
225 case MISCREG_QUEUE_DEV_MONDO_HEAD:
226 case MISCREG_QUEUE_DEV_MONDO_TAIL:
227 case MISCREG_QUEUE_RES_ERROR_HEAD:
228 case MISCREG_QUEUE_RES_ERROR_TAIL:
229 case MISCREG_QUEUE_NRES_ERROR_HEAD:
230 case MISCREG_QUEUE_NRES_ERROR_TAIL:
231 case MISCREG_SOFTINT:
232 case MISCREG_TICK_CMPR:
233 case MISCREG_STICK_CMPR:
234 case MISCREG_PIL:
235 case MISCREG_HPSTATE:
236 case MISCREG_HINTP:
237 case MISCREG_HTSTATE:
238 case MISCREG_HSTICK_CMPR:
239 return readRegNoEffect(miscReg) ;
240
241 case MISCREG_HTBA:
242 return readRegNoEffect(miscReg) & ULL(~0x7FFF);
243 case MISCREG_HVER:
244 // XXX set to match Legion
245 return ULL(0x3e) << 48 |
246 ULL(0x23) << 32 |
247 ULL(0x20) << 24 |
248 //MaxGL << 16 | XXX For some reason legion doesn't set GL
249 MaxTL << 8 |
250 (NWindows -1) << 0;
251
252 case MISCREG_STRAND_STS_REG:
253 System *sys;
254 int x;
255 sys = tc->getSystemPtr();
256
257 temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative);
258 // Check that the CPU array is fully populated
259 // (by calling getNumCPus())
260 assert(sys->getNumCPUs() > tc->readCpuId());
261
262 temp |= tc->readCpuId() << STS::shft_id;
263
264 for (x = tc->readCpuId() & ~3; x < sys->threadContexts.size(); x++) {
265 switch (sys->threadContexts[x]->status()) {
266 case ThreadContext::Active:
267 temp |= STS::st_run << (STS::shft_fsm0 -
268 ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
269 break;
270 case ThreadContext::Suspended:
271 // should this be idle?
272 temp |= STS::st_idle << (STS::shft_fsm0 -
273 ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
274 break;
275 case ThreadContext::Halted:
276 temp |= STS::st_halt << (STS::shft_fsm0 -
277 ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
278 break;
279 default:
280 panic("What state are we in?!\n");
281 } // switch
282 } // for
283
284 return temp;
285 default:
286 panic("Invalid read to FS misc register\n");
287 }
288}
289
290void
291MiscRegFile::processTickCompare(ThreadContext *tc)
292{
293 panic("tick compare not implemented\n");
294}
295
296void
297MiscRegFile::processSTickCompare(ThreadContext *tc)
298{
299 BaseCPU *cpu = tc->getCpuPtr();
300
299 // since our microcode instructions take two cycles we need to check if
300 // we're actually at the correct cycle or we need to wait a little while
301 // more
302 int ticks;
303 ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
301 // since our microcode instructions take two cycles we need to check if
302 // we're actually at the correct cycle or we need to wait a little while
303 // more
304 int ticks;
305 ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
304 tc->getCpuPtr()->instCount();
306 cpu->instCount();
305 assert(ticks >= 0 && "stick compare missed interrupt cycle");
306
307 if (ticks == 0 || tc->status() == ThreadContext::Suspended) {
308 DPRINTF(Timer, "STick compare cycle reached at %#x\n",
309 (stick_cmpr & mask(63)));
310 if (!(tc->readMiscRegNoEffect(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
311 setReg(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
312 }
313 } else
307 assert(ticks >= 0 && "stick compare missed interrupt cycle");
308
309 if (ticks == 0 || tc->status() == ThreadContext::Suspended) {
310 DPRINTF(Timer, "STick compare cycle reached at %#x\n",
311 (stick_cmpr & mask(63)));
312 if (!(tc->readMiscRegNoEffect(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
313 setReg(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
314 }
315 } else
314 sTickCompare->schedule(ticks * tc->getCpuPtr()->ticks(1) + curTick);
316 cpu->schedule(sTickCompare, curTick + ticks * cpu->ticks(1));
315}
316
317void
318MiscRegFile::processHSTickCompare(ThreadContext *tc)
319{
317}
318
319void
320MiscRegFile::processHSTickCompare(ThreadContext *tc)
321{
322 BaseCPU *cpu = tc->getCpuPtr();
323
320 // since our microcode instructions take two cycles we need to check if
321 // we're actually at the correct cycle or we need to wait a little while
322 // more
323 int ticks;
324 if ( tc->status() == ThreadContext::Halted ||
325 tc->status() == ThreadContext::Unallocated)
326 return;
327
328 ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
324 // since our microcode instructions take two cycles we need to check if
325 // we're actually at the correct cycle or we need to wait a little while
326 // more
327 int ticks;
328 if ( tc->status() == ThreadContext::Halted ||
329 tc->status() == ThreadContext::Unallocated)
330 return;
331
332 ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
329 tc->getCpuPtr()->instCount();
333 cpu->instCount();
330 assert(ticks >= 0 && "hstick compare missed interrupt cycle");
331
332 if (ticks == 0 || tc->status() == ThreadContext::Suspended) {
333 DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
334 (stick_cmpr & mask(63)));
335 if (!(tc->readMiscRegNoEffect(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
336 setReg(MISCREG_HINTP, 1, tc);
337 }
338 // Need to do something to cause interrupt to happen here !!! @todo
339 } else
334 assert(ticks >= 0 && "hstick compare missed interrupt cycle");
335
336 if (ticks == 0 || tc->status() == ThreadContext::Suspended) {
337 DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
338 (stick_cmpr & mask(63)));
339 if (!(tc->readMiscRegNoEffect(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
340 setReg(MISCREG_HINTP, 1, tc);
341 }
342 // Need to do something to cause interrupt to happen here !!! @todo
343 } else
340 hSTickCompare->schedule(ticks * tc->getCpuPtr()->ticks(1) + curTick);
344 cpu->schedule(hSTickCompare, curTick + ticks * cpu->ticks(1));
341}
342
345}
346