Exemplo n.º 1
0
void set_cpsr_full(u32 cpsr) {
	if ((cpsr ^ arm.cpsr_low28) & 0x1F) {
		/* Switching to a different processor mode. Swap out registers of old mode */
		if ((arm.cpsr_low28 & 0x1F) == MODE_FIQ)
			memcpy(arm.r8_fiq, &arm.reg[8], 20);
		else
			memcpy(arm.r8_usr, &arm.reg[8], 20);
		switch (arm.cpsr_low28 & 0x1F) {
			case MODE_USR:
			case MODE_SYS: memcpy(arm.r13_usr, &arm.reg[13], 8); break;
			case MODE_FIQ: memcpy(arm.r13_fiq, &arm.reg[13], 8); break;
			case MODE_IRQ: memcpy(arm.r13_irq, &arm.reg[13], 8); break;
			case MODE_SVC: memcpy(arm.r13_svc, &arm.reg[13], 8); break;
			case MODE_ABT: memcpy(arm.r13_abt, &arm.reg[13], 8); break;
			case MODE_UND: memcpy(arm.r13_und, &arm.reg[13], 8); break;
			default:       error("Invalid previous processor mode (This can't happen)\n");
		}

		/* Swap in registers of new mode */
		if ((cpsr & 0x1F) == MODE_FIQ)
			memcpy(&arm.reg[8], arm.r8_fiq, 20);
		else
			memcpy(&arm.reg[8], arm.r8_usr, 20);
		switch (cpsr & 0x1F) {
			case MODE_USR:
			case MODE_SYS: memcpy(&arm.reg[13], arm.r13_usr, 8); break;
			case MODE_FIQ: memcpy(&arm.reg[13], arm.r13_fiq, 8); break;
			case MODE_IRQ: memcpy(&arm.reg[13], arm.r13_irq, 8); break;
			case MODE_SVC: memcpy(&arm.reg[13], arm.r13_svc, 8); break;
			case MODE_ABT: memcpy(&arm.reg[13], arm.r13_abt, 8); break;
			case MODE_UND: memcpy(&arm.reg[13], arm.r13_und, 8); break;
			default:       error("Invalid new processor mode\n");
		}

		/* If going to or from user mode, memory access permissions may be different */
		if (!(arm.cpsr_low28 & 3) || !(cpsr & 3))
			addr_cache_flush();
	}

	if (cpsr & 0x01000000)
		error("J mode is not implemented");

	arm.cpsr_n = cpsr >> 31 & 1;
	arm.cpsr_z = cpsr >> 30 & 1;
	arm.cpsr_c = cpsr >> 29 & 1;
	arm.cpsr_v = cpsr >> 28 & 1;
	arm.cpsr_low28 = cpsr & 0x090000FF; /* Mask off reserved bits */
	cpu_int_check();
}
Exemplo n.º 2
0
void emu_loop(bool reset)
{
    #if OS_HAS_PAGEFAULT_HANDLER
        os_exception_frame_t seh_frame = { NULL, NULL };
        os_faulthandler_arm(&seh_frame);
    #endif

    if(reset)
    {
        reset:
        emu_reset();
    }

    gdbstub_reset();

    addr_cache_flush();
    flush_translations();

    sched_update_next_event(0);

    exiting = false;

// clang segfaults with that, for an iOS build :(
#ifndef NO_SETJMP
    // Workaround for LLVM bug #18974
    while(__builtin_setjmp(restart_after_exception)){};
#endif

    while (!exiting) {
        sched_process_pending_events();
        while (!exiting && cycle_count_delta < 0) {
            if (cpu_events & EVENT_RESET) {
                gui_status_printf("Reset");
                goto reset;
            }

            if (cpu_events & (EVENT_FIQ | EVENT_IRQ)) {
                // Align PC in case the interrupt occurred immediately after a jump
                if (arm.cpsr_low28 & 0x20)
                    arm.reg[15] &= ~1;
                else
                    arm.reg[15] &= ~3;

                if (cpu_events & EVENT_WAITING)
                    arm.reg[15] += 4; // Skip over wait instruction

                arm.reg[15] += 4;
                cpu_exception((cpu_events & EVENT_FIQ) ? EX_FIQ : EX_IRQ);
            }
            cpu_events &= ~EVENT_WAITING;

            if (arm.cpsr_low28 & 0x20)
                cpu_thumb_loop();
            else
                cpu_arm_loop();
        }
    }

    #if OS_HAS_PAGEFAULT_HANDLER
        os_faulthandler_unarm(&seh_frame);
    #endif
}