ulong devportreadlong(Engine *E, State *S, ulong addr) { if (addr == SUPERH_THREADID) { return S->NODE_ID; } else if ((addr >= SUPERH_NUMAREGION_RDCNT_BEGIN) && (addr < SUPERH_NUMAREGION_RDCNT_END)) { /* */ /* CNT register addresses are longword-aligned, */ /* so lower 2 bits of address are irrelevant, */ /* (should always be zero). */ /* */ int which = ((addr - SUPERH_NUMAREGION_RDCNT_BEGIN) >> 2) & 0x3FFF; if (which >= S->N->count) { mprint(E, S, nodeinfo, "Longword access to address [0x" UHLONGFMT "] (NUMAREGION_RDCNT register)\n", addr); mprint(E, S, nodeinfo, "which = %d\n", which); sfatal(E, S, "Attempt to access NUMAREGION_RDCNT register " "outside number of NUMAREGIONs"); } return S->N->regions[which]->nreads; }
void Tracer::fatal(const char* method, const char* message, ...) const { // fatal traces cannot be suppressed! ///@todo with qt4 the follwing code can be used: /* va_list ap; va_start(ap, message); QString str; str.vsprintf(message, ap); va_end(ap); sfatal(method) << str << endl; */ va_list ap; int maxLength = 1024; int result = maxLength; char* str; while (result >= maxLength) { va_start(ap, message); str = (char*)malloc(maxLength); result = vsnprintf(str, maxLength-1, message, ap); va_end(ap); if (result >= maxLength) { delete str; maxLength = 2 * maxLength; result = maxLength; } } sfatal(method) << str << endl; delete str; }
tuck int superHtake_nic_intr(Engine *E, State *S) { Interrupt *interrupt; if (!interruptible(S)) { return -1; } /* */ /* (PC is incremented at end of step() in pipeline.c) */ /* We need to re-exec instruction which is currently in */ /* ID when we RTE, so save that kids PC! (then do a */ /* ifidflush()). If we are faststeping, then S->PC is */ /* the next instr that we would place into EX and exec. */ /* */ /* i.e., at this point, we are yet to execute instruction */ /* @PC (fastep/step below) so rather than setting SPC */ /* to PC+2, we set it to PC, so that RTE executes the */ /* instr after then one after we caught the interrupt. */ /* */ if (S->step == superHfaststep) { S->superH->SPC = S->PC; } else { drain_pipeline(E, S); /* */ /* Must do this after drain because */ /* executed instruction during drain */ /* might set PC (e.g. a BRA) */ /* */ S->superH->SPC = S->PC; } S->superH->SSR = S->superH->SR; S->superH->SR.BL = 1; S->superH->SR.MD = 1; S->superH->SR.RB = 1; S->PC = S->superH->VBR + 0x600; S->sleep = 0; interrupt = (Interrupt *)pic_intr_dequeue(E, S, S->superH->nicintrQ); if (interrupt == NULL) { sfatal(E, S, "We supposedly had an interrupt, but nothing was queued!"); } /* */ /* The value field, which in the case of NIC, specifies */ /* which interface the interrupt was generated by. The */ /* apps. interpret exception codes offset from base as */ /* the interface number (well, you know what i mean...) */ /* */ switch (interrupt->type) { case NIC_RXOK_INTR: { S->superH->INTEVT = (NIC_RX_EXCP_CODE + interrupt->value); break; } case NIC_TXOK_INTR: { S->superH->INTEVT = (NIC_TX_EXCP_CODE + interrupt->value); break; } case NIC_ADDRERR_INTR: { S->superH->INTEVT = (NIC_ADDR_EXCP_CODE + interrupt->value); break; } case NIC_FRAMEERR_INTR: { S->superH->INTEVT = (NIC_FRAME_EXCP_CODE + interrupt->value); break; } case NIC_COLLSERR_INTR: { S->superH->INTEVT = (NIC_COLLS_EXCP_CODE + interrupt->value); break; } case NIC_CSENSEERR_INTR: { S->superH->INTEVT = (NIC_CSENSE_EXCP_CODE + interrupt->value); break; } case NIC_RXOVRRUNERR_INTR: { S->superH->INTEVT = (NIC_RXOVRRUN_EXCP_CODE + interrupt->value); break; } case NIC_RXUNDRRUNERR_INTR: { S->superH->INTEVT = (NIC_RXUNDRRUN_EXCP_CODE + interrupt->value); break; } case NIC_TXOVRRUNERR_INTR: { S->superH->INTEVT = (NIC_TXOVRRUN_EXCP_CODE + interrupt->value); break; } case NIC_TXUNDRRUNERR_INTR: { S->superH->INTEVT = (NIC_TXUNDRRUN_EXCP_CODE + interrupt->value); break; } case NIC_CSUMERR_INTR: { S->superH->INTEVT = (NIC_CSUM_EXCP_CODE + interrupt->value); break; } default: { mprint(E, S, nodeinfo, "Received interrupt type [%d]\n", interrupt->type); sfatal(E, S, "Unknown interrupt type!"); } } mfree(E, interrupt, "Interrupt *interrupt in machine-hitachi-sh.c"); return 0; }
tuck void superHtake_exception(Engine *E, State *S) { enum {ABORTED_AND_RETRIED, ABORTED, COMPLETED, INVALID_HANDLING}; Interrupt *intr; int handling = INVALID_HANDLING; intr = (Interrupt *)pic_intr_dequeue(E, S, S->superH->excpQ); if (intr == NULL) { sfatal(E, S, "We supposedly had an exception, but nothing was queued!"); } S->superH->SSR = S->superH->SR; S->superH->SR.BL = 1; S->superH->SR.MD = 1; S->superH->SR.RB = 1; S->sleep = 0; switch (intr->type) { case H_UDI_RESET_EXCP: { S->PC = RESET_VECTOR_ADDR; S->superH->EXPEVT = H_UDI_RESET_EXCP_CODE; handling = ABORTED; break; } case POWER_ON_RESET_EXCP: { S->PC = RESET_VECTOR_ADDR; S->superH->EXPEVT = POWER_ON_RESET_EXCP_CODE; handling = ABORTED; break; } case MANUAL_RESET_EXCP: { S->PC = RESET_VECTOR_ADDR; S->superH->EXPEVT = MANUAL_RESET_EXCP_CODE; handling = ABORTED; break; } case TLB_LOAD_MISS_EXCP: { S->PC = S->superH->VBR + TLB_MISS_OFFSET; S->superH->EXPEVT = TLB_LOAD_MISS_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case TLB_STORE_MISS_EXCP: { S->PC = S->superH->VBR + TLB_MISS_OFFSET; S->superH->EXPEVT = TLB_STORE_MISS_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case TLB_LOAD_INVALID_EXCP: { S->PC = S->superH->VBR + TLB_INVALID_OFFSET; S->superH->EXPEVT = TLB_LOAD_INVALID_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case TLB_STORE_INVALID_EXCP: { S->PC = S->superH->VBR + TLB_INVALID_OFFSET; S->superH->EXPEVT = TLB_STORE_INVALID_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case TLB_INIT_PAGEWRITE_EXCP: { S->PC = S->superH->VBR + TLB_INIT_PAGEWRITE_OFFSET; S->superH->EXPEVT = TLB_INIT_PAGEWRITE_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case TLB_LOAD_PROTECT_EXCP: { S->PC = S->superH->VBR + TLB_PROTECT_OFFSET; S->superH->EXPEVT = TLB_LOAD_PROTECT_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case TLB_STORE_PROTECT_EXCP: { S->PC = S->superH->VBR + TLB_PROTECT_OFFSET; S->superH->EXPEVT = TLB_STORE_PROTECT_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case CPU_LOAD_ADDRERR_EXCP: { /* Doesn't make a difference; Self documenting. */ if (intr->misc == MEM_ACCESS_IFETCH) { S->PC = S->superH->VBR + CPU_INSTR_ADDRERR_OFFSET; } else { S->PC = S->superH->VBR + CPU_ADDRERR_OFFSET; } S->superH->EXPEVT = CPU_LOAD_ADDRERR_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case CPU_STORE_ADDRERR_EXCP: { S->PC = S->superH->VBR + CPU_ADDRERR_OFFSET; S->superH->EXPEVT = CPU_STORE_ADDRERR_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case TRAPA_EXCP_CODE: { S->PC = S->superH->VBR + TRAPA_OFFSET; S->superH->EXPEVT = TRAPA_EXCP_CODE; handling = COMPLETED; break; } case ILLEGAL_INSTR_EXCP: { S->PC = S->superH->VBR + ILLEGAL_INSTR_OFFSET; S->superH->EXPEVT = ILLEGAL_INSTR_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case ILLEGAL_SLOT_INSTR_EXCP: { S->PC = S->superH->VBR + ILLEGAL_SLOT_INSTR_OFFSET; S->superH->EXPEVT = ILLEGAL_SLOT_INSTR_EXCP_CODE; handling = ABORTED_AND_RETRIED; break; } case USER_BKPOINT_TRAP_EXCP: { S->PC = S->superH->VBR + USER_BKPOINT_OFFSET; S->superH->EXPEVT = USER_BKPOINT_TRAP_EXCP_CODE; handling = COMPLETED; break; } case DMA_ADDRERR_EXCP: { S->PC = S->superH->VBR + DMA_ADDRERR_OFFSET; S->superH->EXPEVT = DMA_ADDRERR_EXCP_CODE; handling = COMPLETED; break; } default: { sfatal(E, S, "Unknown/invalid exception code"); } } if (handling == ABORTED) { /* Current instruction is aborted */ superHpipeflush(S); } else if (handling == ABORTED_AND_RETRIED) { superHpipeflush(S); S->superH->SPC = intr->value; } else if (handling == COMPLETED) { /* Current instruction is completed */ if (S->step == superHfaststep) { S->superH->SPC = S->PC; } else { drain_pipeline(E, S); S->superH->SPC = S->PC; } } mfree(E, intr, "Interrupt *interrupt in machine-hitachi-sh.c"); return; }