ChannelBuilder::ChannelBuilder(uint_t chan, Devices::SAA::Registers& regs) : Channel(chan) , Regs(regs) { SetRegister(Devices::SAA::Registers::TONEMIXER, 0, 1 << chan); SetRegister(Devices::SAA::Registers::NOISEMIXER, 0, 1 << chan); }
static void arm_check_irq_state(void) { data32_t pc = R15+4; /* save old pc (already incremented in pipeline) */; /* Exception priorities (from ARM6, not specifically ARM2/3): Reset Data abort FIRQ IRQ Prefetch abort Undefined instruction */ if (arm.pendingFiq && (pc&F_MASK)==0) { R15 = eARM_MODE_FIQ; /* Set FIQ mode so PC is saved to correct R14 bank */ SetRegister( 14, pc ); /* save PC */ R15 = (pc&PSR_MASK)|0x1c|eARM_MODE_FIQ|I_MASK|F_MASK; /* Mask both IRQ & FIRQ, set PC=0x1c */ return; } if (arm.pendingIrq && (pc&I_MASK)==0) { R15 = eARM_MODE_IRQ; /* Set IRQ mode so PC is saved to correct R14 bank */ SetRegister( 14, pc ); /* save PC */ R15 = (pc&PSR_MASK)|0x18|eARM_MODE_IRQ|I_MASK|(pc&F_MASK); /* Mask only IRQ, set PC=0x18 */ return; } }
virtual void SetFreq(uint_t freq) { Frequency[Channel] = freq; const uint_t chan = Channel % 3; SetRegister(0xa4 + chan, freq >> 8); SetRegister(0xa0 + chan, freq & 0xff); }
bool VIRTUALMACHINE::step(bool skip) { bool result= false; VMREGTYPE ip= 0; OPCODE opcode; if(GetRegister(IP,ip) && GetInstruction((VPVOID)ip,opcode) && opcode) { INSTRUCTIONMAP::iterator it= instructions.find(opcode); if(it!=instructions.end()) { INSTRUCTION* inst= it->second; int operandlength= inst->GetOperands(opcode,(VPVOID)ip+sizeof(opcode)); if(operandlength>=0) { ip+= sizeof(opcode)+operandlength; if(SetRegister(IP,(VMREGTYPE)ip)) { result= skip || inst->execute(); } } } else { BadOpcodeHandler(opcode,(VPVOID)ip); } } return result; }
void InitSoundBlaster (int BaseAddress) { byte i; BaseAddr=BaseAddress; for (i=0; i<=0xF5; i++) SetRegister (i,0); }
bool VIRTUALMACHINE::pop(VMFLOAT& val) { bool result= false; VMREGTYPE sp= 0; if(GetRegister(SP,sp)) { if(SetRegister(SP,sp+sizeof(VMREGTYPE))) result= ReadMem((VPVOID)sp,&val,sizeof(val)); } return result; }
// Preform a system reset void m68000::Reset() { Register pc, ssp; // Reset all of the device's attached to the processor myAddressSpaces[0]->Reset(); // Set the Status register to its reset value register_value[SR_INDEX] = S_FLAG | I0_FLAG | I1_FLAG | I2_FLAG; // Fetch the Supervisor Stack Pointer from location $00000000 if (Peek(0x00000000, ssp, LONG) != EXECUTE_OK) SetRegister(SSP_INDEX, 0, LONG); else SetRegister(SSP_INDEX, ssp, LONG); // Fetch the Program Counter from location $00000004 if (Peek(0x00000004, pc, LONG) != EXECUTE_OK) SetRegister(PC_INDEX, 0, LONG); else SetRegister(PC_INDEX, pc, LONG); // Put the processor in normal instrution execution mode myState = NORMAL_STATE; }
bool VIRTUALMACHINE::push(VMFLOAT val) { bool result= false; VMREGTYPE sp= 0; if(GetRegister(SP,sp)) { sp-= sizeof(VMREGTYPE); if(SetRegister(SP,sp)) { SetFlags(val); result= WriteMem((VPVOID)sp,&val,sizeof(val)); } } return result; }
static void HandleBranch( data32_t insn ) { data32_t off = (insn & INSN_BRANCH) << 2; /* Save PC into LR if this is a branch with link */ if (insn & INSN_BL) { SetRegister(14,R15 + 4); } /* Sign-extend the 24-bit offset in our calculations */ if (off & 0x2000000u) { R15 -= ((~(off | 0xfc000000u)) + 1) - 8; } else { R15 += off + 8; } }
static void HandleBranch( ARM_REGS* cpustate, UINT32 insn ) { UINT32 off = (insn & INSN_BRANCH) << 2; /* Save PC into LR if this is a branch with link */ if (insn & INSN_BL) { SetRegister(cpustate, 14,R15 + 4); } /* Sign-extend the 24-bit offset in our calculations */ if (off & 0x2000000u) { R15 -= ((~(off | 0xfc000000u)) + 1) - 8; } else { R15 += off + 8; } cpustate->icount -= 2 * S_CYCLE + N_CYCLE; }
void HandleBranch(UINT32 insn) { UINT32 off = (insn & INSN_BRANCH) << 2; /* Save PC into LR if this is a branch with link */ if (insn & INSN_BL) { SetRegister(14, R15+ 4); } /* Sign-extend the 24-bit offset in our calculations */ if (off & 0x2000000u) { R15 = ((R15 - (((~(off | 0xfc000000u)) + 1) - 8)) & ADDRESS_MASK) | (R15 & ~ADDRESS_MASK); } else { R15 = ((R15 + (off + 8)) & ADDRESS_MASK) | (R15 & ~ADDRESS_MASK); } CYCLE_COUNT(2 * S_CYCLE + N_CYCLE); }
void arm_cpu_device::HandleBranch( UINT32 insn ) { UINT32 off = (insn & INSN_BRANCH) << 2; /* Save PC into LR if this is a branch with link */ if (insn & INSN_BL) { SetRegister(14,R15 + 4); } /* Sign-extend the 24-bit offset in our calculations */ if (off & 0x2000000u) { R15 -= ((~(off | 0xfc000000u)) + 1) - 8; } else { R15 += off + 8; } m_icount -= 2 * S_CYCLE + N_CYCLE; }
void arm_cpu_device::HandleBranch( uint32_t insn ) { uint32_t off = (insn & INSN_BRANCH) << 2; /* Save PC into LR if this is a branch with link */ if (insn & INSN_BL) { SetRegister(14,R15 + 4); } /* Sign-extend the 24-bit offset in our calculations */ if (off & 0x2000000u) { R15 = ((R15 - (((~(off | 0xfc000000u)) + 1) - 8)) & ADDRESS_MASK) | (R15 & ~ADDRESS_MASK); } else { R15 = ((R15 + (off + 8)) & ADDRESS_MASK) | (R15 & ~ADDRESS_MASK); } m_icount -= 2 * S_CYCLE + N_CYCLE; }
void arm_set_sp(unsigned val) { SetRegister(13,val); }
int arm_execute( int cycles ) { data32_t pc; data32_t insn; arm_ICount = cycles; do { #ifdef MAME_DEBUG if (mame_debug) MAME_Debug(); #endif /* load instruction */ pc = R15; insn = READ32( pc & ADDRESS_MASK ); switch (insn >> INSN_COND_SHIFT) { case COND_EQ: if (Z_IS_CLEAR(pc)) goto L_Next; break; case COND_NE: if (Z_IS_SET(pc)) goto L_Next; break; case COND_CS: if (C_IS_CLEAR(pc)) goto L_Next; break; case COND_CC: if (C_IS_SET(pc)) goto L_Next; break; case COND_MI: if (N_IS_CLEAR(pc)) goto L_Next; break; case COND_PL: if (N_IS_SET(pc)) goto L_Next; break; case COND_VS: if (V_IS_CLEAR(pc)) goto L_Next; break; case COND_VC: if (V_IS_SET(pc)) goto L_Next; break; case COND_HI: if (C_IS_CLEAR(pc) || Z_IS_SET(pc)) goto L_Next; break; case COND_LS: if (C_IS_SET(pc) && Z_IS_CLEAR(pc)) goto L_Next; break; case COND_GE: if (!(pc & N_MASK) != !(pc & V_MASK)) goto L_Next; /* Use x ^ (x >> ...) method */ break; case COND_LT: if (!(pc & N_MASK) == !(pc & V_MASK)) goto L_Next; break; case COND_GT: if (Z_IS_SET(pc) || (!(pc & N_MASK) != !(pc & V_MASK))) goto L_Next; break; case COND_LE: if (Z_IS_CLEAR(pc) && (!(pc & N_MASK) == !(pc & V_MASK))) goto L_Next; break; case COND_NV: goto L_Next; } /* Condition satisfied, so decode the instruction */ if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */ { HandleMul(insn); R15 += 4; } else if (!(insn & 0x0c000000u)) /* Data processing */ { HandleALU(insn); } else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */ { HandleMemSingle(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */ { HandleMemBlock(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */ { HandleBranch(insn); } else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */ { pc=R15+4; R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */ SetRegister( 14, pc ); /* save PC */ R15 = (pc&PSR_MASK)|0x8|eARM_MODE_SVC|(pc&MODE_MASK); } else /* Undefined */ { logerror("%08x: Undefined instruction\n",R15); L_Next: arm_ICount -= S_CYCLE; R15 += 4; } arm_ICount -= 3; } while( arm_ICount > 0 ); return cycles - arm_ICount; } /* arm_execute */
void arm_cpu_device::HandleMemSingle( UINT32 insn ) { UINT32 rn, rnv, off, rd; /* Fetch the offset */ if (insn & INSN_I) { off = decodeShift(insn, NULL); } else { off = insn & INSN_SDT_IMM; } /* Calculate Rn, accounting for PC */ rn = (insn & INSN_RN) >> INSN_RN_SHIFT; // if (rn==0xf) logerror("%08x: Source R15\n",R15); if (insn & INSN_SDT_P) { /* Pre-indexed addressing */ if (insn & INSN_SDT_U) { if (rn != eR15) rnv = (GetRegister(rn) + off); else rnv = (R15 & ADDRESS_MASK) + off; } else { if (rn != eR15) rnv = (GetRegister(rn) - off); else rnv = (R15 & ADDRESS_MASK) - off; } if (insn & INSN_SDT_W) { SetRegister(rn,rnv); if (ARM_DEBUG_CORE && rn == eR15) logerror("writeback R15 %08x\n", R15); } else if (rn == eR15) { rnv = rnv + 8; } } else { /* Post-indexed addressing */ if (rn == eR15) { rnv = (R15 & ADDRESS_MASK) + 8; } else { rnv = GetRegister(rn); } } /* Do the transfer */ rd = (insn & INSN_RD) >> INSN_RD_SHIFT; if (insn & INSN_SDT_L) { /* Load */ m_icount -= S_CYCLE + I_CYCLE + N_CYCLE; if (insn & INSN_SDT_B) { if (ARM_DEBUG_CORE && rd == eR15) logerror("read byte R15 %08x\n", R15); SetRegister(rd,(UINT32) cpu_read8(rnv) ); } else { if (rd == eR15) { R15 = (cpu_read32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); /* The docs are explicit in that the bottom bits should be masked off when writing to R15 in this way, however World Cup Volleyball 95 has an example of an unaligned jump (bottom bits = 2) where execution should definitely continue from the rounded up address. In other cases, 4 is subracted from R15 here to account for pipelining. */ if ((cpu_read32(rnv)&3)==0) R15 -= 4; m_icount -= S_CYCLE + N_CYCLE; } else { SetRegister(rd, cpu_read32(rnv)); } } } else { /* Store */ m_icount -= 2 * N_CYCLE; if (insn & INSN_SDT_B) { if (ARM_DEBUG_CORE && rd==eR15) logerror("Wrote R15 in byte mode\n"); cpu_write8(rnv, (UINT8) GetRegister(rd) & 0xffu); } else { if (ARM_DEBUG_CORE && rd==eR15) logerror("Wrote R15 in 32bit mode\n"); cpu_write32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); } } /* Do post-indexing writeback */ if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/) { if (insn & INSN_SDT_U) { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); } else { if ((insn&INSN_SDT_W)!=0) logerror("%08x: RegisterWritebackIncrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); SetRegister(rn,(rnv + off)); } } else { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); } else { SetRegister(rn,(rnv - off)); if ((insn&INSN_SDT_W)!=0) logerror("%08x: RegisterWritebackDecrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); } } } } /* HandleMemSingle */
void arm_cpu_device::execute_run() { UINT32 pc; UINT32 insn; do { debugger_instruction_hook(this, R15 & ADDRESS_MASK); /* load instruction */ pc = R15; insn = m_direct->read_decrypted_dword( pc & ADDRESS_MASK ); switch (insn >> INSN_COND_SHIFT) { case COND_EQ: if (Z_IS_CLEAR(pc)) goto L_Next; break; case COND_NE: if (Z_IS_SET(pc)) goto L_Next; break; case COND_CS: if (C_IS_CLEAR(pc)) goto L_Next; break; case COND_CC: if (C_IS_SET(pc)) goto L_Next; break; case COND_MI: if (N_IS_CLEAR(pc)) goto L_Next; break; case COND_PL: if (N_IS_SET(pc)) goto L_Next; break; case COND_VS: if (V_IS_CLEAR(pc)) goto L_Next; break; case COND_VC: if (V_IS_SET(pc)) goto L_Next; break; case COND_HI: if (C_IS_CLEAR(pc) || Z_IS_SET(pc)) goto L_Next; break; case COND_LS: if (C_IS_SET(pc) && Z_IS_CLEAR(pc)) goto L_Next; break; case COND_GE: if (!(pc & N_MASK) != !(pc & V_MASK)) goto L_Next; /* Use x ^ (x >> ...) method */ break; case COND_LT: if (!(pc & N_MASK) == !(pc & V_MASK)) goto L_Next; break; case COND_GT: if (Z_IS_SET(pc) || (!(pc & N_MASK) != !(pc & V_MASK))) goto L_Next; break; case COND_LE: if (Z_IS_CLEAR(pc) && (!(pc & N_MASK) == !(pc & V_MASK))) goto L_Next; break; case COND_NV: goto L_Next; } /* Condition satisfied, so decode the instruction */ if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */ { HandleMul(insn); R15 += 4; } else if (!(insn & 0x0c000000u)) /* Data processing */ { HandleALU(insn); } else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */ { HandleMemSingle(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */ { HandleMemBlock(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */ { HandleBranch(insn); } else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */ { if (m_copro_type == ARM_COPRO_TYPE_VL86C020) HandleCoProVL86C020(insn); else HandleCoPro(insn); R15 += 4; } else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */ { pc=R15+4; R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */ SetRegister( 14, pc ); /* save PC */ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK); m_icount -= 2 * S_CYCLE + N_CYCLE; } else /* Undefined */ { logerror("%08x: Undefined instruction\n",R15); L_Next: m_icount -= S_CYCLE; R15 += 4; } arm_check_irq_state(); } while( m_icount > 0 ); } /* arm_execute */
static void arm7_set_info(UINT32 state, cpuinfo *info) { switch (state) { /* --- the following bits of info are set as 64-bit signed integers --- */ /* interrupt lines/exceptions */ case CPUINFO_INT_INPUT_STATE + ARM7_IRQ_LINE: set_irq_line(ARM7_IRQ_LINE, info->i); break; case CPUINFO_INT_INPUT_STATE + ARM7_FIRQ_LINE: set_irq_line(ARM7_FIRQ_LINE, info->i); break; case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_EXCEPTION: set_irq_line(ARM7_ABORT_EXCEPTION, info->i); break; case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_PREFETCH_EXCEPTION: set_irq_line(ARM7_ABORT_PREFETCH_EXCEPTION, info->i); break; case CPUINFO_INT_INPUT_STATE + ARM7_UNDEFINE_EXCEPTION: set_irq_line(ARM7_UNDEFINE_EXCEPTION, info->i); break; /* registers shared by all operating modes */ case CPUINFO_INT_REGISTER + ARM7_R0: ARM7REG( 0) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R1: ARM7REG( 1) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R2: ARM7REG( 2) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R3: ARM7REG( 3) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R4: ARM7REG( 4) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R5: ARM7REG( 5) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R6: ARM7REG( 6) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R7: ARM7REG( 7) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R8: ARM7REG( 8) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R9: ARM7REG( 9) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R10: ARM7REG(10) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R11: ARM7REG(11) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R12: ARM7REG(12) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R13: ARM7REG(13) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R14: ARM7REG(14) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_R15: ARM7REG(15) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_CPSR: SET_CPSR(info->i); break; case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + ARM7_PC: R15 = info->i; break; case CPUINFO_INT_SP: SetRegister(13,info->i); break; /* FIRQ Mode Shadowed Registers */ case CPUINFO_INT_REGISTER + ARM7_FR8: ARM7REG(eR8_FIQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_FR9: ARM7REG(eR9_FIQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_FR10: ARM7REG(eR10_FIQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_FR11: ARM7REG(eR11_FIQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_FR12: ARM7REG(eR12_FIQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_FR13: ARM7REG(eR13_FIQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_FR14: ARM7REG(eR14_FIQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_FSPSR: ARM7REG(eSPSR_FIQ) = info->i; break; /* IRQ Mode Shadowed Registers */ case CPUINFO_INT_REGISTER + ARM7_IR13: ARM7REG(eR13_IRQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_IR14: ARM7REG(eR14_IRQ) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_ISPSR: ARM7REG(eSPSR_IRQ) = info->i; break; /* Supervisor Mode Shadowed Registers */ case CPUINFO_INT_REGISTER + ARM7_SR13: ARM7REG(eR13_SVC) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_SR14: ARM7REG(eR14_SVC) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_SSPSR: ARM7REG(eSPSR_SVC) = info->i; break; /* Abort Mode Shadowed Registers */ case CPUINFO_INT_REGISTER + ARM7_AR13: ARM7REG(eR13_ABT) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_AR14: ARM7REG(eR14_ABT) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_ASPSR: ARM7REG(eSPSR_ABT) = info->i; break; /* Undefined Mode Shadowed Registers */ case CPUINFO_INT_REGISTER + ARM7_UR13: ARM7REG(eR13_UND) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_UR14: ARM7REG(eR14_UND) = info->i; break; case CPUINFO_INT_REGISTER + ARM7_USPSR: ARM7REG(eSPSR_UND) = info->i; break; } }
int ArmRun( int cycles ) { UINT32 pc; UINT32 insn; arm_icount = cycles; arm.ArmLeftCycles = cycles; do { /* load instruction */ pc = R15; insn = Arm_program_opcode_dword_32le( pc & ADDRESS_MASK ); switch (insn >> INSN_COND_SHIFT) { case COND_EQ: if (Z_IS_CLEAR(pc)) goto L_Next; break; case COND_NE: if (Z_IS_SET(pc)) goto L_Next; break; case COND_CS: if (C_IS_CLEAR(pc)) goto L_Next; break; case COND_CC: if (C_IS_SET(pc)) goto L_Next; break; case COND_MI: if (N_IS_CLEAR(pc)) goto L_Next; break; case COND_PL: if (N_IS_SET(pc)) goto L_Next; break; case COND_VS: if (V_IS_CLEAR(pc)) goto L_Next; break; case COND_VC: if (V_IS_SET(pc)) goto L_Next; break; case COND_HI: if (C_IS_CLEAR(pc) || Z_IS_SET(pc)) goto L_Next; break; case COND_LS: if (C_IS_SET(pc) && Z_IS_CLEAR(pc)) goto L_Next; break; case COND_GE: if (!(pc & N_MASK) != !(pc & V_MASK)) goto L_Next; /* Use x ^ (x >> ...) method */ break; case COND_LT: if (!(pc & N_MASK) == !(pc & V_MASK)) goto L_Next; break; case COND_GT: if (Z_IS_SET(pc) || (!(pc & N_MASK) != !(pc & V_MASK))) goto L_Next; break; case COND_LE: if (Z_IS_CLEAR(pc) && (!(pc & N_MASK) == !(pc & V_MASK))) goto L_Next; break; case COND_NV: goto L_Next; } /* Condition satisfied, so decode the instruction */ if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */ { HandleMul(insn); R15 += 4; } else if (!(insn & 0x0c000000u)) /* Data processing */ { HandleALU(insn); } else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */ { HandleMemSingle(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */ { HandleMemBlock(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */ { HandleBranch(insn); } else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */ { HandleCoPro(insn); R15 += 4; } else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */ { pc=R15+4; R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */ SetRegister( 14, pc ); /* save PC */ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK); change_pc(pc&ADDRESS_MASK); arm_icount -= 2 * S_CYCLE + N_CYCLE; } else /* Undefined */ { L_Next: arm_icount -= S_CYCLE; R15 += 4; } arm_check_irq_state(); } while( arm_icount > 0 ); arm.ArmTotalCycles += (cycles - arm_icount); return cycles - arm_icount; } /* arm_execute */
void arm2_execute_run(int tube_cycles) { #ifdef TRACE int i; #endif UINT32 pc; UINT32 insn; //int m_icount = number; do { //debugger_instruction_hook(this, R15 & ADDRESS_MASK); /* load instruction */ pc = R15; #ifdef INCLUDE_DEBUGGER if (arm2_debug_enabled) { debug_preexec(&arm2_cpu_debug, pc & ADDRESS_MASK); } #endif insn = cpu_read32( pc & ADDRESS_MASK ); #ifdef TRACE if ((pc & ADDRESS_MASK) == 0xa060) { m_trace = 1; } if (m_trace) { printf("%08X %08X ", pc, insn); for (i = eR0; i <= eR7; i++) { printf("%08X ", m_sArmRegister[i]); } if(darm_armv7_disasm(&d, insn) == 0 && darm_str2(&d, &str, 0) == 0) { printf("%s\r\n", str.total); } else { printf("***\r\n"); } } if ((pc & ADDRESS_MASK) == 0xa0c0) { m_trace = 0; } if ((pc & ADDRESS_MASK) == 0xa2ac) { m_trace = 0; } if ((insn & 0x0D900000) == 0x01000000) { printf("S bit not set in %08x at %08x\r\n", insn, pc & ADDRESS_MASK); insn |= INSN_S; } #endif switch (insn >> INSN_COND_SHIFT) { case COND_EQ: if (Z_IS_CLEAR(pc)) goto L_Next; break; case COND_NE: if (Z_IS_SET(pc)) goto L_Next; break; case COND_CS: if (C_IS_CLEAR(pc)) goto L_Next; break; case COND_CC: if (C_IS_SET(pc)) goto L_Next; break; case COND_MI: if (N_IS_CLEAR(pc)) goto L_Next; break; case COND_PL: if (N_IS_SET(pc)) goto L_Next; break; case COND_VS: if (V_IS_CLEAR(pc)) goto L_Next; break; case COND_VC: if (V_IS_SET(pc)) goto L_Next; break; case COND_HI: if (C_IS_CLEAR(pc) || Z_IS_SET(pc)) goto L_Next; break; case COND_LS: if (C_IS_SET(pc) && Z_IS_CLEAR(pc)) goto L_Next; break; case COND_GE: if (!(pc & N_MASK) != !(pc & V_MASK)) goto L_Next; /* Use x ^ (x >> ...) method */ break; case COND_LT: if (!(pc & N_MASK) == !(pc & V_MASK)) goto L_Next; break; case COND_GT: if (Z_IS_SET(pc) || (!(pc & N_MASK) != !(pc & V_MASK))) goto L_Next; break; case COND_LE: if (Z_IS_CLEAR(pc) && (!(pc & N_MASK) == !(pc & V_MASK))) goto L_Next; break; case COND_NV: goto L_Next; } /* Condition satisfied, so decode the instruction */ if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */ { HandleMul(insn); R15 += 4; } else if (!(insn & 0x0c000000u)) /* Data processing */ { HandleALU(insn); } else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */ { HandleMemSingle(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */ { HandleMemBlock(insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */ { HandleBranch(insn); } else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */ { if (m_copro_type == ARM_COPRO_TYPE_VL86C020) HandleCoProVL86C020(insn); else HandleCoPro(insn); R15 += 4; } else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */ { pc=R15+4; R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */ SetRegister( 14, pc ); /* save PC */ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK); CYCLE_COUNT(2 * S_CYCLE + N_CYCLE); } else /* Undefined */ { logerror("%08x: Undefined instruction\n",R15); L_Next: CYCLE_COUNT(S_CYCLE); R15 += 4; } //arm2_check_irq_state(); tubeUseCycles(1); } while (tubeContinueRunning()); //while( m_icount > 0 ); //while (number--); } /* arm_execute */
static CPU_EXECUTE( arm ) { UINT32 pc; UINT32 insn; ARM_REGS *cpustate = get_safe_token(device); cpustate->icount = cycles; do { debugger_instruction_hook(device, R15 & ADDRESS_MASK); /* load instruction */ pc = R15; insn = memory_decrypted_read_dword( cpustate->program, pc & ADDRESS_MASK ); switch (insn >> INSN_COND_SHIFT) { case COND_EQ: if (Z_IS_CLEAR(pc)) goto L_Next; break; case COND_NE: if (Z_IS_SET(pc)) goto L_Next; break; case COND_CS: if (C_IS_CLEAR(pc)) goto L_Next; break; case COND_CC: if (C_IS_SET(pc)) goto L_Next; break; case COND_MI: if (N_IS_CLEAR(pc)) goto L_Next; break; case COND_PL: if (N_IS_SET(pc)) goto L_Next; break; case COND_VS: if (V_IS_CLEAR(pc)) goto L_Next; break; case COND_VC: if (V_IS_SET(pc)) goto L_Next; break; case COND_HI: if (C_IS_CLEAR(pc) || Z_IS_SET(pc)) goto L_Next; break; case COND_LS: if (C_IS_SET(pc) && Z_IS_CLEAR(pc)) goto L_Next; break; case COND_GE: if (!(pc & N_MASK) != !(pc & V_MASK)) goto L_Next; /* Use x ^ (x >> ...) method */ break; case COND_LT: if (!(pc & N_MASK) == !(pc & V_MASK)) goto L_Next; break; case COND_GT: if (Z_IS_SET(pc) || (!(pc & N_MASK) != !(pc & V_MASK))) goto L_Next; break; case COND_LE: if (Z_IS_CLEAR(pc) && (!(pc & N_MASK) == !(pc & V_MASK))) goto L_Next; break; case COND_NV: goto L_Next; } /* Condition satisfied, so decode the instruction */ if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */ { HandleMul(cpustate, insn); R15 += 4; } else if (!(insn & 0x0c000000u)) /* Data processing */ { HandleALU(cpustate, insn); } else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */ { HandleMemSingle(cpustate, insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */ { HandleMemBlock(cpustate, insn); R15 += 4; } else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */ { HandleBranch(cpustate, insn); } else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */ { HandleCoPro(cpustate, insn); R15 += 4; } else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */ { pc=R15+4; R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */ SetRegister( cpustate, 14, pc ); /* save PC */ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK); cpustate->icount -= 2 * S_CYCLE + N_CYCLE; } else /* Undefined */ { logerror("%08x: Undefined instruction\n",R15); L_Next: cpustate->icount -= S_CYCLE; R15 += 4; } arm_check_irq_state(cpustate); } while( cpustate->icount > 0 ); return cycles - cpustate->icount; } /* arm_execute */
void ChannelBuilder::SetEnvelope(uint_t type) { SetRegister(Devices::SAA::Registers::ENVELOPE0 + (Channel >= 3), type); }
// Service pending interrupts, serviceFlag set true iff something serviced int m68000::ServiceInterrupts(bool &serviceFlag) { serviceFlag = false; // If there are no pending interupts, return normally. if (pending_interrupts.empty()) { return EXECUTE_OK; } const PendingInterrupt &interrupt = pending_interrupts.top(); // Also return normally if any of the currently pending interrupts // are masked. Note that a check against the top of the queue is // sufficient, as the top entry has the highest level. const int interrupt_mask = (register_value[SR_INDEX] & 0x0700) >> 8; if (interrupt.level < interrupt_mask && interrupt.level != 7) { return EXECUTE_OK; } // Put the processor into normal state if it's stopped if (myState == STOP_STATE) myState = NORMAL_STATE; // Save a copy of the current SR so it can be stacked for entry // to the interrupt service subroutine Register tmp_sr = register_value[SR_INDEX]; // Set the Interrupt Mask in SR register_value[SR_INDEX] &= 0x0000f8ff; register_value[SR_INDEX] |= (interrupt.level << 8); // Change to Supervisor mode and clear the Trace mode register_value[SR_INDEX] |= S_FLAG; register_value[SR_INDEX] &= ~T_FLAG; // Interrupt has occured so push the PC and the SR SetRegister(SSP_INDEX, register_value[SSP_INDEX] - 4, LONG); int status = Poke(register_value[SSP_INDEX], register_value[PC_INDEX], LONG); if (status != EXECUTE_OK) return status; SetRegister(SSP_INDEX, register_value[SSP_INDEX] - 2, LONG); status = Poke(register_value[SSP_INDEX], tmp_sr, WORD); if (status != EXECUTE_OK) return status; // Get the vector number by acknowledging to the device int vector = interrupt.device->InterruptAcknowledge(interrupt.level); if (vector == AUTOVECTOR_INTERRUPT) vector = 24 + interrupt.level; else if (vector == SPURIOUS_INTERRUPT) vector = 24; // Get the interrupt service routine's address Address service_address; status = Peek(vector * 4, service_address, LONG); if (status != EXECUTE_OK) return status; // Change the program counter to the service routine's address SetRegister(PC_INDEX, service_address, LONG); // Indicate that an interrupt was serviced and remove it from // the queue of pending interrupts serviceFlag = true; pending_interrupts.pop(); return EXECUTE_OK; }
static void HandleMemSingle( data32_t insn ) { data32_t rn, rnv, off, rd; /* Fetch the offset */ if (insn & INSN_I) { off = decodeShift(insn, NULL); } else { off = insn & INSN_SDT_IMM; } /* Calculate Rn, accounting for PC */ rn = (insn & INSN_RN) >> INSN_RN_SHIFT; // if (rn==0xf) logerror("%08x: Source R15\n",R15); if (insn & INSN_SDT_P) { /* Pre-indexed addressing */ if (insn & INSN_SDT_U) { rnv = (GetRegister(rn) + off); } else { rnv = (GetRegister(rn) - off); } if (insn & INSN_SDT_W) { SetRegister(rn,rnv); //check writeback??? } else if (rn == eR15) { rnv = (rnv & ADDRESS_MASK) + 8; } } else { /* Post-indexed addressing */ if (rn == eR15) { rnv = (R15 & ADDRESS_MASK) + 8; } else { rnv = GetRegister(rn); } } /* Do the transfer */ rd = (insn & INSN_RD) >> INSN_RD_SHIFT; if (insn & INSN_SDT_L) { /* Load */ if (insn & INSN_SDT_B) { SetRegister(rd,(data32_t) READ8(rnv)); } else { if (rd == eR15) { if (ARM_DEBUG_CORE) logerror("%08x: LDR to R15\n",R15); R15 = (READ32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); R15 -= 4; } else { SetRegister(rd,READ32(rnv)); } } } else { /* Store */ if (insn & INSN_SDT_B) { if (ARM_DEBUG_CORE && rd==eR15) logerror("Wrote R15 in byte mode\n"); WRITE8(rnv, (data8_t) GetRegister(rd) & 0xffu); } else { if (ARM_DEBUG_CORE && rd==eR15) logerror("Wrote R15 in 32bit mode\n"); WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); } } /* Do post-indexing writeback */ if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/) { if (insn & INSN_SDT_U) { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); //todo: check for offs... ? } else { if ((insn&INSN_SDT_W)!=0) logerror("%08x: RegisterWritebackIncrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); SetRegister(rn,(rnv + off)); } } else { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); // logerror("Arm %08x: LDR style with rn==rn\n",R15); } else { SetRegister(rn,(rnv - off)); if ((insn&INSN_SDT_W)!=0) logerror("%08x: RegisterWritebackDecrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0); } } } // arm_check_irq_state() } /* HandleMemSingle */
void ChannelBuilder::SetVolume(int_t left, int_t right) { SetRegister(Devices::SAA::Registers::LEVEL0 + Channel, 16 * Math::Clamp<int_t>(right, 0, 15) + Math::Clamp<int_t>(left, 0, 15)); }
virtual void SetKeyOn() { const uint_t key = Channel < 3 ? Channel : Channel + 1; SetRegister(0x28, 0xf0 | key); }
void ChannelBuilder::SetTone(uint_t octave, uint_t note) { SetRegister(Devices::SAA::Registers::TONENUMBER0 + Channel, note); AddRegister(Devices::SAA::Registers::TONEOCTAVE01 + Channel / 2, 0 != (Channel & 1) ? (octave << 4) : octave); }
static void HandleMemSingle( UINT32 insn ) { UINT32 rn, rnv, off, rd; /* Fetch the offset */ if (insn & INSN_I) { off = decodeShift(insn, NULL); } else { off = insn & INSN_SDT_IMM; } /* Calculate Rn, accounting for PC */ rn = (insn & INSN_RN) >> INSN_RN_SHIFT; if (insn & INSN_SDT_P) { /* Pre-indexed addressing */ if (insn & INSN_SDT_U) { rnv = (GetRegister(rn) + off); } else { rnv = (GetRegister(rn) - off); } if (insn & INSN_SDT_W) { SetRegister(rn,rnv); } else if (rn == eR15) { rnv = (rnv & ADDRESS_MASK) + 8; } } else { /* Post-indexed addressing */ if (rn == eR15) { rnv = (R15 & ADDRESS_MASK) + 8; } else { rnv = GetRegister(rn); } } /* Do the transfer */ rd = (insn & INSN_RD) >> INSN_RD_SHIFT; if (insn & INSN_SDT_L) { /* Load */ arm_icount -= S_CYCLE + I_CYCLE + N_CYCLE; if (insn & INSN_SDT_B) { SetRegister(rd,(UINT32) READ8(rnv)); } else { if (rd == eR15) { R15 = (READ32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK); change_pc(R15 & ADDRESS_MASK); /* The docs are explicit in that the bottom bits should be masked off when writing to R15 in this way, however World Cup Volleyball 95 has an example of an unaligned jump (bottom bits = 2) where execution should definitely continue from the rounded up address. In other cases, 4 is subracted from R15 here to account for pipelining. */ if ((READ32(rnv)&3)==0) R15 -= 4; arm_icount -= S_CYCLE + N_CYCLE; } else { SetRegister(rd,READ32(rnv)); } } } else { /* Store */ arm_icount -= 2 * N_CYCLE; if (insn & INSN_SDT_B) { WRITE8(rnv, (UINT8) GetRegister(rd) & 0xffu); } else { WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(rd)); } } /* Do post-indexing writeback */ if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/) { if (insn & INSN_SDT_U) { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); } else { SetRegister(rn,(rnv + off)); } } else { /* Writeback is applied in pipeline, before value is read from mem, so writeback is effectively ignored */ if (rd==rn) { SetRegister(rn,GetRegister(rd)); } else { SetRegister(rn,(rnv - off)); } } } } /* HandleMemSingle */
/** * Handles the setregisters sub-command. * * @returns Suitable exit code. * @param pArgs The handler arguments. * @param pDebugger Pointer to the debugger interface. */ static RTEXITCODE handleDebugVM_SetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger) { /* * We take a list of register assignments, that is register=value. */ ULONG idCpu = 0; com::SafeArray<IN_BSTR> aBstrNames; com::SafeArray<IN_BSTR> aBstrValues; RTGETOPTSTATE GetState; RTGETOPTUNION ValueUnion; static const RTGETOPTDEF s_aOptions[] = { { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, }; int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); AssertRCReturn(rc, RTEXITCODE_FAILURE); while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) { switch (rc) { case 'c': idCpu = ValueUnion.u32; break; case VINF_GETOPT_NOT_OPTION: { const char *pszEqual = strchr(ValueUnion.psz, '='); if (!pszEqual) return errorSyntax("setregisters expects input on the form 'register=value' got '%s'", ValueUnion.psz); try { com::Bstr bstrName(ValueUnion.psz, pszEqual - ValueUnion.psz); com::Bstr bstrValue(pszEqual + 1); if ( !aBstrNames.push_back(bstrName.raw()) || !aBstrValues.push_back(bstrValue.raw())) throw std::bad_alloc(); } catch (std::bad_alloc) { RTMsgError("Out of memory\n"); return RTEXITCODE_FAILURE; } break; } default: return errorGetOpt(rc, &ValueUnion); } } if (!aBstrNames.size()) return errorSyntax("The setregisters sub-command takes at least one register name"); /* * If it is only one register, use the single register method just so * we expose it and can test it from the command line. */ if (aBstrNames.size() == 1) { CHECK_ERROR2I_RET(pDebugger, SetRegister(idCpu, aBstrNames[0], aBstrValues[0]), RTEXITCODE_FAILURE); RTPrintf("Successfully set %ls\n", aBstrNames[0]); } else { CHECK_ERROR2I_RET(pDebugger, SetRegisters(idCpu, ComSafeArrayAsInParam(aBstrNames), ComSafeArrayAsInParam(aBstrValues)), RTEXITCODE_FAILURE); RTPrintf("Successfully set %u registers\n", aBstrNames.size()); } return RTEXITCODE_SUCCESS; }
void ChannelBuilder::SetNoise(uint_t type) { const uint_t shift = Channel >= 3 ? 4 : 0; SetRegister(Devices::SAA::Registers::NOISECLOCK, type << shift, 0x7 << shift); }