Reply 40 of 63, by superfury
Well, the protection is handled by the MMU during all memory reads/writes (including CPU instruction reads). So when an instructions reads data from memory (any instruction opcode/parameter) an exception is triggered and executed after which the CPU core itself aborts executing the instruction when it gets to the 'execution' part. Anything before that simply parses the data as if it were valid data (in fact, the only part of the full CPU emulation that actually parses such data is the CPU core REP/REPZ/REPNZ check and the 'execution' phase in opcodes_80*86.c(which executes the instruction itself and decodes modr/m when used with the instruction). All other parts will try to handle it if possible or raise an exception if it hasn't been triggered already during the 'decoding' phase by the CPU core (cpu.c) or modr/m core(modrm.c's modrm_decode8/16/32). The modrm_decode8/16/32 is called by modrm_readparams, which is in turn called by the instruction handler itself (opcodes_80*86.c). The instruction handler is called by cpu.c(the 'core' of the CPU handling containing all basic CPU functionality and special actions (stack, REP, related initialisation calls(MMU, MODR/M, instruction fetching) for every instruction).
Currently without the prefetching all instruction fetching is handled by CPU_readOP(w/dw). This function in turn calls MMU_r(b/w/dw) which handles protected mode from the MMU(including all checks and exceptions) and accesses memory and MMI/O hardware.
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io