nepx / halfix

x86 PC emulator that runs both natively and in the browser, via WebAssembly
https://nepx.github.io/halfix-demo/
GNU General Public License v3.0
669 stars 86 forks source link

Initialize FPU by default #5

Closed DCNick3 closed 4 years ago

DCNick3 commented 4 years ago

Even though real operating systems will initialize FPU during their boot process (by issuing finit instruction), it would be more convenient for libcpu user if the FPU was already initialized.

nepx commented 4 years ago

Hello,

There's number of ways that the FPU can be initialized. Every operating system will do it differently -- for instance, OS/2 handles floating point exceptions using IRQ13. I added a routine that will do just that, but that's just the way that mine (Linux x86-64) does it. If it doesn't suit your needs (to simulate OS/2, for instance), you'll have to tinker with some of the bits yourself.

Alternatively, you can map a page to memory, write a bit of shellcode, and then execute it:

static uint8_t mem[4096];
static uint8_t data[] = { 0x0F, 0x20, 0xC0, 0x83, 0xE0, 0xF3, 0x83, 0xC8, 0x20, 0x0F, 0x22, 0xC0, 0xDB, 0xE3 };

/*
Disassembly, for those interested: 
0:  0f 20 c0                mov    eax,cr0
3:  83 e0 f3                and    eax,0xfffffff3 // ~(TS | EM)
6:  83 c8 20                or     eax,0x20
9:  0f 22 c0                mov    cr0,eax
c:  db e3                   fninit 
*/

static void* mem_stuff(uint32_t addr, int write)
{
    UNUSED(write);
    return mem + addr;
}

void setup_cpu(void)
{
    cpu_init();
    cpu_init_32bit();
    memcpy(mem, data, 14); 
    cpu_set_state(CPU_PHYSEIP, 0);
    cpu_register_mem_refill_handler(mem_stuff);
    cpu_run(5);
}