int32 icr_rd () { uint32 delta = sim_grtime() - tmr_sav; if (tmr_iccs & TMR_CSR_RUN) /* running? */ return (int32)(tmr_nicr + ((1000000.0 * delta) / sim_timer_inst_per_sec ())); return (int32)tmr_icr; }
void tmr_sched (uint32 nicr) { uint32 usecs = (nicr) ? (~nicr + 1) : 0xFFFFFFFF; clk_tps = 1000000 / usecs; sim_debug (TMR_DB_SCHED, &tmr_dev, "tmr_sched(nicr=0x%08X-usecs=0x%08X) - tps=%d\n", nicr, usecs, clk_tps); tmr_poll = sim_rtcn_calb (clk_tps, TMR_CLK); if (SCPE_OK == sim_activate_after (&tmr_unit, usecs)) tmr_sav = sim_grtime(); /* Save interval base time */ }
void tmr_sched (void) { tmr_sav = sim_grtime (); /* save intvl base */ tmr_inc = (~tmr_icr + 1); /* inc = interval */ if (tmr_inc == 0) tmr_inc = 1; if (tmr_inc < TMR_INC) { /* 100Hz multiple? */ sim_activate (&tmr_unit, tmr_inc); /* schedule timer */ tmr_use_100hz = 0; } else tmr_use_100hz = 1; /* let clk handle */ return; }
int32 icr_rd (void) { int32 result; if (tmr_iccs & TMR_CSR_RUN) { /* running? */ uint32 delta = sim_grtime() - tmr_sav; result = (int32)(tmr_nicr + (uint32)((1000000.0 * delta) / sim_timer_inst_per_sec ())); } else result = (int32)tmr_icr; sim_debug (TMR_DB_REG, &tmr_dev, "icr_rd() = 0x%08X%s\n", result, (tmr_iccs & TMR_CSR_RUN) ? " - interpolated" : ""); return result; }
int32 icr_rd (t_bool interp) { uint32 delta; if (interp || (tmr_iccs & TMR_CSR_RUN)) { /* interp, running? */ delta = sim_grtime () - tmr_sav; /* delta inst */ if (tmr_use_100hz && (tmr_poll > TMR_INC)) /* scale large int */ delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll); if (delta >= tmr_inc) delta = tmr_inc - 1; return tmr_icr + delta; } return tmr_icr; }
t_stat cpu_one_inst (uint32 opc, uint32 ir) { uint32 ea, op, dat, res, dev, sh4, ch; t_bool ovf_this_cycle = FALSE; t_stat reason = 0; op = I_GETOP (ir); /* opcode */ ea = I_GETEA (ir); /* address */ switch (op) { /* case on opcode */ /* Loads, stores, transfers instructions */ case OP_B: /* bring */ A = Read (ea); /* A <- M[ea] */ delay = I_delay (opc, ea, op); break; case OP_H: /* hold */ Write (ea, A); /* M[ea] <- A */ delay = I_delay (opc, ea, op); break; case OP_C: /* clear */ Write (ea, A); /* M[ea] <- A */ A = 0; /* A <- 0 */ delay = I_delay (opc, ea, op); break; case OP_Y: /* store address */ dat = Read (ea); /* get operand */ dat = (dat & ~I_EA) | (A & I_EA); /* merge address */ Write (ea, dat); delay = I_delay (opc, ea, op); break; case OP_R: /* return address */ dat = Read (ea); /* get operand */ dat = (dat & ~I_EA) | (((PC + 1) & AMASK) << I_V_EA); Write (ea, dat); delay = I_delay (opc, ea, op); break; case OP_U: /* uncond transfer */ PCQ_ENTRY; PC = ea; /* transfer */ delay = I_delay (opc, ea, op); break; case OP_T: /* conditional transfer */ if ((A & SIGN) || /* A < 0 or */ ((ir & SIGN) && t_switch)) { /* -T and Tswitch set? */ PCQ_ENTRY; PC = ea; /* transfer */ } delay = I_delay (opc, ea, op); break; /* Arithmetic and logical instructions */ case OP_A: /* add */ dat = Read (ea); /* get operand */ res = (A + dat) & DMASK; /* add */ if ((~A ^ dat) & (dat ^ res) & SIGN) /* calc overflow */ ovf_this_cycle = TRUE; A = res; /* save result */ delay = I_delay (opc, ea, op); break; case OP_S: /* sub */ dat = Read (ea); /* get operand */ res = (A - dat) & DMASK; /* subtract */ if ((A ^ dat) & (~dat ^ res) & SIGN) /* calc overflow */ ovf_this_cycle = TRUE; A = res; delay = I_delay (opc, ea, op); break; case OP_M: /* multiply high */ dat = Read (ea); /* get operand */ A = (Mul64 (A, dat, NULL) << 1) & DMASK; /* multiply */ delay = I_delay (opc, ea, op); break; case OP_N: /* multiply low */ dat = Read (ea); /* get operand */ Mul64 (A, dat, &res); /* multiply */ A = res; /* keep low result */ delay = I_delay (opc, ea, op); /* total delay */ break; case OP_D: /* divide */ dat = Read (ea); /* get operand */ if (Div32 (A, dat, &A)) /* divide; overflow? */ ovf_this_cycle = TRUE; delay = I_delay (opc, ea, op); break; case OP_E: /* extract */ dat = Read (ea); /* get operand */ A = A & dat; /* and */ delay = I_delay (opc, ea, op); break; /* IO instructions */ case OP_P: /* output */ if (Q_LGP21) { /* LGP-21 */ ch = A >> 26; /* char, 6b */ if (ir & SIGN) /* 4b? convert */ ch = (ch & 0x3C) | 2; dev = I_GETTK (ir); /* device select */ } else { /* LGP-30 */ ch = I_GETTK (ir); /* char, always 6b */ dev = Q_OUTPT? DEV_PT: DEV_TT; /* device select */ } reason = op_p (dev & DEV_MASK, ch); /* output */ delay = I_delay (sim_grtime (), ea, op); /* next instruction */ break; case OP_I: /* input */ if (Q_LGP21) { /* LGP-21 */ ch = 0; /* initial shift */ sh4 = ir & SIGN; /* 4b/6b select */ dev = I_GETTK (ir); /* device select */ } else { /* LGP-30 */ ch = I_GETTK (ir); /* initial shift */ sh4 = Q_IN4B; /* 4b/6b select */ dev = Q_INPT? DEV_PT: DEV_TT; /* device select */ } if (dev == DEV_SHIFT) /* shift? */ A = shift_in (A, 0, sh4); /* shift 4/6b */ else reason = op_i (dev & DEV_MASK, ch, sh4); /* input */ delay = I_delay (sim_grtime (), ea, op); /* next instruction */ break; case OP_Z: if (Q_LGP21) { /* LGP-21 */ if (ea & 0xF80) { /* no stop? */ if (((ea & 0x800) && !bp32) || /* skip if any */ ((ea & 0x400) && !bp16) || /* selected switch */ ((ea & 0x200) && !bp8) || /* is off */ ((ea & 0x100) && !bp4) || /* or if */ ((ir & SIGN) && !OVF)) /* ovf sel and off */ PC = (PC + 1) & AMASK; if (ir & SIGN) /* -Z? clr overflow */ OVF = 0; } else { /* stop */ lgp21_sov = (ir & SIGN)? 1: 0; /* pending sense? */ reason = STOP_STOP; /* stop */ } } else { /* LGP-30 */ if (out_done) /* P complete? */ out_done = 0; else if (((ea & 0x800) && bp32) || /* bpt switch set? */ ((ea & 0x400) && bp16) || ((ea & 0x200) && bp8) || ((ea & 0x100) && bp4)) ; /* don't stop or stall */ else if (out_strt) /* P pending? stall */ reason = STOP_STALL; else reason = STOP_STOP; /* no, stop */ } delay = I_delay (sim_grtime (), ea, op); /* next instruction */ break; /* end switch */ }
void tmr_sched (uint32 nicr) { sim_activate_after (&tmr_unit, (nicr) ? (~nicr + 1) : 0xFFFFFFFF); tmr_sav = sim_grtime(); }