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(); } }