Generally speaking, there are two basic modes of operation:
- User mode (a protected mode for running applications)
- System mode (an unprotected mode for initialisation and system functions)
The mode is specified by the flags, but these can't be changed directly (at least without creating a heap of nasty edge cases).
Besides the user-mode/system-mode flag there are also flags to enable/disable exceptions, and there can be other kinds of modes indicated by the flags as well (for example, a mode advanced chip could use these to enable/disable caching or other functionality).
Regardless of which modes are supported, there are exactly three scenarios in which mode switching occurs:
- At reset, the mode flags are initialised to sane values (it will be operating in system mode, with interrupts disabled)
- Manually using a
before
(0xB4) instruction (which generally "returns from a system call" but might otherwise be used just to jump to a different mode) - When an exception occurs (which is either triggered by an invalid or misbehaving instruction, or by a timer/bus/IO device)
The exception number (and the address at which the exception occurred) can be determined from the control registers.
Unable to fetch instruction (i.e. bad instruction address or fatal bus error).
Instruction was fetched but not recognised as valid by the decoder.
Instruction was fetched and could presumably be decoded, but requires system mode and was run in user mode.
The instruction was fetched/decoded but the memory or extension I/O triggered a bus exception.
The instruction was fetched/decoded but referred to a register which was unimplemented or blocked.
The instruction was fetched/decoded but the ALU operation triggered an error (e.g. bad operation or division by zero).
This exception number is reserved for system calls (which would currently trigger an EXCN_INVALIDINSTR).
This exception is triggered by the internal timer unit (if enabled) i.e. for multitasking or other regular checks.
This exception is triggered by external hardware, typically an interrupt controller (which should have it's own mechanism for interrupt numbers).