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();
}
static void update() {
	u32 prev_raw_status = intr.raw_status;
	intr.raw_status = intr.active ^ ~intr.noninverted;

	intr.sticky_status |= (intr.raw_status & ~prev_raw_status);
	intr.status = (intr.raw_status    & ~intr.sticky)
	            | (intr.sticky_status &  intr.sticky);

	int is_fiq;
	for (is_fiq = 0; is_fiq < 2; is_fiq++) {
		int i = -1;
		get_current_int(is_fiq, &i);
		if (i >= 0) {
			arm.interrupts |= 0x80 >> is_fiq;
			cpu_int_check();
		}
	}