Fixes for regression build errors.
[gem5.git] / cpu / o3 / alpha_cpu_impl.hh
1 /*
2 * Copyright (c) 2004-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/alpha/faults.hh"
30 #include "base/cprintf.hh"
31 #include "base/statistics.hh"
32 #include "base/timebuf.hh"
33 #include "cpu/checker/exec_context.hh"
34 #include "cpu/quiesce_event.hh"
35 #include "mem/mem_interface.hh"
36 #include "sim/sim_events.hh"
37 #include "sim/stats.hh"
38
39 #include "cpu/o3/alpha_cpu.hh"
40 #include "cpu/o3/alpha_params.hh"
41 #include "cpu/o3/comm.hh"
42 #include "cpu/o3/thread_state.hh"
43
44 #if FULL_SYSTEM
45 #include "arch/alpha/osfpal.hh"
46 #include "arch/isa_traits.hh"
47 #endif
48
49 using namespace TheISA;
50
51 template <class Impl>
52 AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
53 #if FULL_SYSTEM
54 : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
55 #else
56 : FullO3CPU<Impl>(params)
57 #endif
58 {
59 DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
60
61 this->thread.resize(this->numThreads);
62
63 for (int i = 0; i < this->numThreads; ++i) {
64 #if FULL_SYSTEM
65 assert(this->numThreads == 1);
66 this->thread[i] = new Thread(this, 0, params->mem);
67 this->thread[i]->setStatus(ExecContext::Suspended);
68 #else
69 if (i < params->workload.size()) {
70 DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
71 "process is %#x",
72 i, params->workload[i]->prog_entry, this->thread[i]);
73 this->thread[i] = new Thread(this, i, params->workload[i], i);
74 assert(params->workload[i]->getMemory() != NULL);
75
76 this->thread[i]->setStatus(ExecContext::Suspended);
77 //usedTids[i] = true;
78 //threadMap[i] = i;
79 } else {
80 //Allocate Empty execution context so M5 can use later
81 //when scheduling threads to CPU
82 Process* dummy_proc = NULL;
83
84 this->thread[i] = new Thread(this, i, dummy_proc, i);
85 //usedTids[i] = false;
86 }
87 #endif // !FULL_SYSTEM
88
89 this->thread[i]->numInst = 0;
90
91 ExecContext *xc_proxy;
92
93 AlphaXC *alpha_xc_proxy = new AlphaXC;
94
95 if (params->checker) {
96 xc_proxy = new CheckerExecContext<AlphaXC>(alpha_xc_proxy, this->checker);
97 } else {
98 xc_proxy = alpha_xc_proxy;
99 }
100
101 alpha_xc_proxy->cpu = this;
102 alpha_xc_proxy->thread = this->thread[i];
103
104 alpha_xc_proxy->quiesceEvent =
105 new EndQuiesceEvent(xc_proxy);
106 alpha_xc_proxy->lastActivate = 0;
107 alpha_xc_proxy->lastSuspend = 0;
108
109 this->thread[i]->xcProxy = xc_proxy;
110
111 this->execContexts.push_back(xc_proxy);
112 }
113
114
115 for (int i=0; i < this->numThreads; i++) {
116 this->thread[i]->funcExeInst = 0;
117 }
118
119 // Sets CPU pointers. These must be set at this level because the CPU
120 // pointers are defined to be the highest level of CPU class.
121 this->fetch.setCPU(this);
122 this->decode.setCPU(this);
123 this->rename.setCPU(this);
124 this->iew.setCPU(this);
125 this->commit.setCPU(this);
126
127 this->rob.setCPU(this);
128 this->regFile.setCPU(this);
129
130 lockAddr = 0;
131 lockFlag = false;
132 }
133
134 template <class Impl>
135 void
136 AlphaFullCPU<Impl>::regStats()
137 {
138 // Register stats for everything that has stats.
139 this->fullCPURegStats();
140 this->fetch.regStats();
141 this->decode.regStats();
142 this->rename.regStats();
143 this->iew.regStats();
144 this->commit.regStats();
145 }
146
147 #if FULL_SYSTEM
148 template <class Impl>
149 void
150 AlphaFullCPU<Impl>::AlphaXC::dumpFuncProfile()
151 {
152 // Currently not supported
153 }
154 #endif
155
156 template <class Impl>
157 void
158 AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context)
159 {
160 // some things should already be set up
161 assert(getMemPtr() == old_context->getMemPtr());
162 #if FULL_SYSTEM
163 assert(getSystemPtr() == old_context->getSystemPtr());
164 #else
165 assert(getProcessPtr() == old_context->getProcessPtr());
166 #endif
167
168 // copy over functional state
169 setStatus(old_context->status());
170 copyArchRegs(old_context);
171 setCpuId(old_context->readCpuId());
172 #if !FULL_SYSTEM
173 thread->funcExeInst = old_context->readFuncExeInst();
174 #else
175 EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
176 if (other_quiesce) {
177 // Point the quiesce event's XC at this XC so that it wakes up
178 // the proper CPU.
179 other_quiesce->xc = this;
180 }
181 if (thread->quiesceEvent) {
182 thread->quiesceEvent->xc = this;
183 }
184 // storeCondFailures = 0;
185 cpu->lockFlag = false;
186 #endif
187
188 old_context->setStatus(ExecContext::Unallocated);
189
190 thread->inSyscall = false;
191 thread->trapPending = false;
192 }
193
194 template <class Impl>
195 void
196 AlphaFullCPU<Impl>::AlphaXC::activate(int delay)
197 {
198 DPRINTF(FullCPU, "Calling activate on AlphaXC\n");
199
200 if (thread->status() == ExecContext::Active)
201 return;
202
203 lastActivate = curTick;
204
205 if (thread->status() == ExecContext::Unallocated) {
206 cpu->activateWhenReady(thread->tid);
207 return;
208 }
209
210 thread->setStatus(ExecContext::Active);
211
212 // status() == Suspended
213 cpu->activateContext(thread->tid, delay);
214 }
215
216 template <class Impl>
217 void
218 AlphaFullCPU<Impl>::AlphaXC::suspend()
219 {
220 DPRINTF(FullCPU, "Calling suspend on AlphaXC\n");
221
222 if (thread->status() == ExecContext::Suspended)
223 return;
224
225 lastActivate = curTick;
226 lastSuspend = curTick;
227 /*
228 #if FULL_SYSTEM
229 // Don't change the status from active if there are pending interrupts
230 if (cpu->check_interrupts()) {
231 assert(status() == ExecContext::Active);
232 return;
233 }
234 #endif
235 */
236 thread->setStatus(ExecContext::Suspended);
237 cpu->suspendContext(thread->tid);
238 }
239
240 template <class Impl>
241 void
242 AlphaFullCPU<Impl>::AlphaXC::deallocate()
243 {
244 DPRINTF(FullCPU, "Calling deallocate on AlphaXC\n");
245
246 if (thread->status() == ExecContext::Unallocated)
247 return;
248
249 thread->setStatus(ExecContext::Unallocated);
250 cpu->deallocateContext(thread->tid);
251 }
252
253 template <class Impl>
254 void
255 AlphaFullCPU<Impl>::AlphaXC::halt()
256 {
257 DPRINTF(FullCPU, "Calling halt on AlphaXC\n");
258
259 if (thread->status() == ExecContext::Halted)
260 return;
261
262 thread->setStatus(ExecContext::Halted);
263 cpu->haltContext(thread->tid);
264 }
265
266 template <class Impl>
267 void
268 AlphaFullCPU<Impl>::AlphaXC::regStats(const std::string &name)
269 {}
270
271 template <class Impl>
272 void
273 AlphaFullCPU<Impl>::AlphaXC::serialize(std::ostream &os)
274 {}
275
276 template <class Impl>
277 void
278 AlphaFullCPU<Impl>::AlphaXC::unserialize(Checkpoint *cp, const std::string &section)
279 {}
280
281 #if FULL_SYSTEM
282 template <class Impl>
283 EndQuiesceEvent *
284 AlphaFullCPU<Impl>::AlphaXC::getQuiesceEvent()
285 {
286 return quiesceEvent;
287 }
288
289 template <class Impl>
290 Tick
291 AlphaFullCPU<Impl>::AlphaXC::readLastActivate()
292 {
293 return lastActivate;
294 }
295
296 template <class Impl>
297 Tick
298 AlphaFullCPU<Impl>::AlphaXC::readLastSuspend()
299 {
300 return lastSuspend;
301 }
302
303 template <class Impl>
304 void
305 AlphaFullCPU<Impl>::AlphaXC::profileClear()
306 {}
307
308 template <class Impl>
309 void
310 AlphaFullCPU<Impl>::AlphaXC::profileSample()
311 {}
312 #endif
313
314 template <class Impl>
315 TheISA::MachInst
316 AlphaFullCPU<Impl>::AlphaXC:: getInst()
317 {
318 return thread->inst;
319 }
320
321 template <class Impl>
322 void
323 AlphaFullCPU<Impl>::AlphaXC::copyArchRegs(ExecContext *xc)
324 {
325 // This function will mess things up unless the ROB is empty and
326 // there are no instructions in the pipeline.
327 unsigned tid = thread->tid;
328 PhysRegIndex renamed_reg;
329
330 // First loop through the integer registers.
331 for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
332 renamed_reg = cpu->renameMap[tid].lookup(i);
333
334 DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
335 "now has data %lli.\n",
336 renamed_reg, cpu->readIntReg(renamed_reg),
337 xc->readIntReg(i));
338
339 cpu->setIntReg(renamed_reg, xc->readIntReg(i));
340 }
341
342 // Then loop through the floating point registers.
343 for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
344 renamed_reg = cpu->renameMap[tid].lookup(i + AlphaISA::FP_Base_DepTag);
345 cpu->setFloatRegDouble(renamed_reg,
346 xc->readFloatRegDouble(i));
347 cpu->setFloatRegInt(renamed_reg,
348 xc->readFloatRegInt(i));
349 }
350
351 // Copy the misc regs.
352 cpu->regFile.miscRegs[tid].copyMiscRegs(xc);
353
354 // Then finally set the PC and the next PC.
355 cpu->setPC(xc->readPC(), tid);
356 cpu->setNextPC(xc->readNextPC(), tid);
357 #if !FULL_SYSTEM
358 this->thread->funcExeInst = xc->readFuncExeInst();
359 #endif
360 }
361
362 template <class Impl>
363 void
364 AlphaFullCPU<Impl>::AlphaXC::clearArchRegs()
365 {}
366
367 template <class Impl>
368 uint64_t
369 AlphaFullCPU<Impl>::AlphaXC::readIntReg(int reg_idx)
370 {
371 DPRINTF(Fault, "Reading int register through the XC!\n");
372 return cpu->readArchIntReg(reg_idx, thread->tid);
373 }
374
375 template <class Impl>
376 float
377 AlphaFullCPU<Impl>::AlphaXC::readFloatRegSingle(int reg_idx)
378 {
379 DPRINTF(Fault, "Reading float register through the XC!\n");
380 return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
381 }
382
383 template <class Impl>
384 double
385 AlphaFullCPU<Impl>::AlphaXC::readFloatRegDouble(int reg_idx)
386 {
387 DPRINTF(Fault, "Reading float register through the XC!\n");
388 return cpu->readArchFloatRegDouble(reg_idx, thread->tid);
389 }
390
391 template <class Impl>
392 uint64_t
393 AlphaFullCPU<Impl>::AlphaXC::readFloatRegInt(int reg_idx)
394 {
395 DPRINTF(Fault, "Reading floatint register through the XC!\n");
396 return cpu->readArchFloatRegInt(reg_idx, thread->tid);
397 }
398
399 template <class Impl>
400 void
401 AlphaFullCPU<Impl>::AlphaXC::setIntReg(int reg_idx, uint64_t val)
402 {
403 DPRINTF(Fault, "Setting int register through the XC!\n");
404 cpu->setArchIntReg(reg_idx, val, thread->tid);
405
406 if (!thread->trapPending && !thread->inSyscall) {
407 cpu->squashFromXC(thread->tid);
408 }
409 }
410
411 template <class Impl>
412 void
413 AlphaFullCPU<Impl>::AlphaXC::setFloatRegSingle(int reg_idx, float val)
414 {
415 DPRINTF(Fault, "Setting float register through the XC!\n");
416 cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
417
418 if (!thread->trapPending && !thread->inSyscall) {
419 cpu->squashFromXC(thread->tid);
420 }
421 }
422
423 template <class Impl>
424 void
425 AlphaFullCPU<Impl>::AlphaXC::setFloatRegDouble(int reg_idx, double val)
426 {
427 DPRINTF(Fault, "Setting float register through the XC!\n");
428 cpu->setArchFloatRegDouble(reg_idx, val, thread->tid);
429
430 if (!thread->trapPending && !thread->inSyscall) {
431 cpu->squashFromXC(thread->tid);
432 }
433 }
434
435 template <class Impl>
436 void
437 AlphaFullCPU<Impl>::AlphaXC::setFloatRegInt(int reg_idx, uint64_t val)
438 {
439 DPRINTF(Fault, "Setting floatint register through the XC!\n");
440 cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
441
442 if (!thread->trapPending && !thread->inSyscall) {
443 cpu->squashFromXC(thread->tid);
444 }
445 }
446
447 template <class Impl>
448 void
449 AlphaFullCPU<Impl>::AlphaXC::setPC(uint64_t val)
450 {
451 cpu->setPC(val, thread->tid);
452
453 if (!thread->trapPending && !thread->inSyscall) {
454 cpu->squashFromXC(thread->tid);
455 }
456 }
457
458 template <class Impl>
459 void
460 AlphaFullCPU<Impl>::AlphaXC::setNextPC(uint64_t val)
461 {
462 cpu->setNextPC(val, thread->tid);
463
464 if (!thread->trapPending && !thread->inSyscall) {
465 cpu->squashFromXC(thread->tid);
466 }
467 }
468
469 template <class Impl>
470 Fault
471 AlphaFullCPU<Impl>::AlphaXC::setMiscReg(int misc_reg, const MiscReg &val)
472 {
473 DPRINTF(Fault, "Setting misc register through the XC!\n");
474
475 Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->tid);
476
477 if (!thread->trapPending && !thread->inSyscall) {
478 cpu->squashFromXC(thread->tid);
479 }
480
481 return ret_fault;
482 }
483
484 template <class Impl>
485 Fault
486 AlphaFullCPU<Impl>::AlphaXC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
487 {
488 DPRINTF(Fault, "Setting misc register through the XC!\n");
489
490 Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->tid);
491
492 if (!thread->trapPending && !thread->inSyscall) {
493 cpu->squashFromXC(thread->tid);
494 }
495
496 return ret_fault;
497 }
498
499 #if !FULL_SYSTEM
500
501 template <class Impl>
502 TheISA::IntReg
503 AlphaFullCPU<Impl>::AlphaXC::getSyscallArg(int i)
504 {
505 return cpu->getSyscallArg(i, thread->tid);
506 }
507
508 template <class Impl>
509 void
510 AlphaFullCPU<Impl>::AlphaXC::setSyscallArg(int i, IntReg val)
511 {
512 cpu->setSyscallArg(i, val, thread->tid);
513 }
514
515 template <class Impl>
516 void
517 AlphaFullCPU<Impl>::AlphaXC::setSyscallReturn(SyscallReturn return_value)
518 {
519 cpu->setSyscallReturn(return_value, thread->tid);
520 }
521
522 #endif // FULL_SYSTEM
523
524 template <class Impl>
525 MiscReg
526 AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
527 {
528 return this->regFile.readMiscReg(misc_reg, tid);
529 }
530
531 template <class Impl>
532 MiscReg
533 AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
534 unsigned tid)
535 {
536 return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
537 }
538
539 template <class Impl>
540 Fault
541 AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
542 {
543 return this->regFile.setMiscReg(misc_reg, val, tid);
544 }
545
546 template <class Impl>
547 Fault
548 AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
549 unsigned tid)
550 {
551 return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
552 }
553
554 template <class Impl>
555 void
556 AlphaFullCPU<Impl>::squashFromXC(unsigned tid)
557 {
558 this->thread[tid]->inSyscall = true;
559 this->commit.generateXCEvent(tid);
560 }
561
562 #if FULL_SYSTEM
563
564 template <class Impl>
565 void
566 AlphaFullCPU<Impl>::post_interrupt(int int_num, int index)
567 {
568 BaseCPU::post_interrupt(int_num, index);
569
570 if (this->thread[0]->status() == ExecContext::Suspended) {
571 DPRINTF(IPI,"Suspended Processor awoke\n");
572 // xcProxies[0]->activate();
573 this->execContexts[0]->activate();
574 }
575 }
576
577 template <class Impl>
578 int
579 AlphaFullCPU<Impl>::readIntrFlag()
580 {
581 return this->regFile.readIntrFlag();
582 }
583
584 template <class Impl>
585 void
586 AlphaFullCPU<Impl>::setIntrFlag(int val)
587 {
588 this->regFile.setIntrFlag(val);
589 }
590
591 template <class Impl>
592 Fault
593 AlphaFullCPU<Impl>::hwrei(unsigned tid)
594 {
595 // Need to clear the lock flag upon returning from an interrupt.
596 this->lockFlag = false;
597
598 this->kernelStats->hwrei();
599
600 this->checkInterrupts = true;
601
602 // FIXME: XXX check for interrupts? XXX
603 return NoFault;
604 }
605
606 template <class Impl>
607 bool
608 AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid)
609 {
610 if (this->kernelStats)
611 this->kernelStats->callpal(palFunc,
612 this->execContexts[tid]);
613
614 switch (palFunc) {
615 case PAL::halt:
616 halt();
617 if (--System::numSystemsRunning == 0)
618 new SimExitEvent("all cpus halted");
619 break;
620
621 case PAL::bpt:
622 case PAL::bugchk:
623 if (this->system->breakpoint())
624 return false;
625 break;
626 }
627
628 return true;
629 }
630
631 template <class Impl>
632 void
633 AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid)
634 {
635 fault->invoke(this->execContexts[tid]);
636 }
637
638 template <class Impl>
639 void
640 AlphaFullCPU<Impl>::processInterrupts()
641 {
642 // Check for interrupts here. For now can copy the code that
643 // exists within isa_fullsys_traits.hh. Also assume that thread 0
644 // is the one that handles the interrupts.
645 // @todo: Possibly consolidate the interrupt checking code.
646 // @todo: Allow other threads to handle interrupts.
647
648 // Check if there are any outstanding interrupts
649 //Handle the interrupts
650 int ipl = 0;
651 int summary = 0;
652
653 this->checkInterrupts = false;
654
655 if (this->readMiscReg(IPR_ASTRR, 0))
656 panic("asynchronous traps not implemented\n");
657
658 if (this->readMiscReg(IPR_SIRR, 0)) {
659 for (int i = INTLEVEL_SOFTWARE_MIN;
660 i < INTLEVEL_SOFTWARE_MAX; i++) {
661 if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
662 // See table 4-19 of the 21164 hardware reference
663 ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
664 summary |= (ULL(1) << i);
665 }
666 }
667 }
668
669 uint64_t interrupts = this->intr_status();
670
671 if (interrupts) {
672 for (int i = INTLEVEL_EXTERNAL_MIN;
673 i < INTLEVEL_EXTERNAL_MAX; i++) {
674 if (interrupts & (ULL(1) << i)) {
675 // See table 4-19 of the 21164 hardware reference
676 ipl = i;
677 summary |= (ULL(1) << i);
678 }
679 }
680 }
681
682 if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
683 this->setMiscReg(IPR_ISR, summary, 0);
684 this->setMiscReg(IPR_INTID, ipl, 0);
685 if (this->checker) {
686 this->checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
687 this->checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
688 }
689 this->trap(Fault(new InterruptFault), 0);
690 DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
691 this->readMiscReg(IPR_IPLR, 0), ipl, summary);
692 }
693 }
694
695 #endif // FULL_SYSTEM
696
697 #if !FULL_SYSTEM
698
699 template <class Impl>
700 void
701 AlphaFullCPU<Impl>::syscall(int tid)
702 {
703 DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
704
705 DPRINTF(Activity,"Activity: syscall() called.\n");
706
707 // Temporarily increase this by one to account for the syscall
708 // instruction.
709 ++(this->thread[tid]->funcExeInst);
710
711 // Execute the actual syscall.
712 this->thread[tid]->syscall();
713
714 // Decrease funcExeInst by one as the normal commit will handle
715 // incrementing it.
716 --(this->thread[tid]->funcExeInst);
717 }
718
719 template <class Impl>
720 TheISA::IntReg
721 AlphaFullCPU<Impl>::getSyscallArg(int i, int tid)
722 {
723 return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
724 }
725
726 template <class Impl>
727 void
728 AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
729 {
730 this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
731 }
732
733 template <class Impl>
734 void
735 AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
736 {
737 // check for error condition. Alpha syscall convention is to
738 // indicate success/failure in reg a3 (r19) and put the
739 // return value itself in the standard return value reg (v0).
740 if (return_value.successful()) {
741 // no error
742 this->setArchIntReg(SyscallSuccessReg, 0, tid);
743 this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
744 } else {
745 // got an error, return details
746 this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
747 this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
748 }
749 }
750 #endif