/* * Currently only SBs are frpizable */ bool El_is_frpizable(Hyperblock *hb) { Op *op; Operand pred; /* See if there are any ops guarded by a predicate */ /* Also, no table jumps allowed */ for (Region_ops_C0_order op_i(hb); op_i!=0; op_i++) { op = *op_i; if (op->predicated()) { pred = op->src(PRED1); if (! pred.is_predicate_true()) return (false); } if (op->flag(EL_OPER_TABLE_JUMP)) return (false); } return (true); }
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 */ }