void umull_inst(ARMProc *proc, UWord instruction) { #ifdef DEBUG printf("Ejecutaste un umull\n"); #endif UWord RdLo = get_bits(instruction,12,4); UWord RdHi = get_bits(instruction,16,4); Word Rs = get_bits(instruction,8,4); Word Rm = get_bits(instruction,0,4); Word S = get_bits(instruction,20,1); Word carry; Word result; Word z; Word Hi; Word Lo; if(cond(proc,instruction)){ Mul64(*proc->r[Rm],*proc->r[Rs],&Hi,&Lo); *proc->r[RdLo] = Lo; *proc->r[RdHi] = Hi; if(S == 1){ set_status(proc,status_n,get_bits(*proc->r[RdHi],31,1)); if(*proc->r[RdHi] == 0 && *proc->r[RdLo] == 0) z = 1; else z = 0; set_status(proc,status_z,z); } } }
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 */ }