diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 72b322330..06e383012 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -1348,6 +1348,13 @@ void exec386_dynarec(int cycs) valid_block = 0; } } + if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP) + { + /*FPU top-of-stack does not match the value this block was compiled + with, re-compile using dynamic top-of-stack*/ + block->flags &= ~CODEBLOCK_STATIC_TOP; + block->was_recompiled = 0; + } } if (valid_block && block->was_recompiled) diff --git a/src/codegen.h b/src/codegen.h index c15f85e77..f12b04895 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -56,10 +56,17 @@ typedef struct codeblock_t uint64_t page_mask, page_mask2; int was_recompiled; + uint32_t flags; + int TOP; uint8_t data[2048]; } codeblock_t; +/*Code block uses FPU*/ +#define CODEBLOCK_HAS_FPU 1 +/*Code block is always entered with the same FPU top-of-stack*/ +#define CODEBLOCK_STATIC_TOP 2 + static inline codeblock_t *codeblock_tree_find(uint32_t phys) { codeblock_t *block = pages[phys >> 12].head; diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index b46010349..1d1b71010 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -1838,427 +1838,642 @@ static void FP_ENTER() static void FP_FLD(int reg) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (reg) + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); + addbyte(0xf3); /*MOVQ XMM0, ST[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0xf3); /*MOVQ XMM1, MM[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x4d); + addbyte(cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x66); /*MOVQ ST[-1][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addbyte(0x8a); /*MOV AL, tag[reg][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x66); /*MOVQ MM[-1][EBP], XMM1*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x4d); + addbyte(cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x88); /*MOV tag[-1][EBP], AL*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); } else { - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(0x01); - } + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (reg) + { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } + else + { + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + } - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(0x07); - addbyte(0x8b); /*MOV EDX, [ST_i64+EAX]*/ - addbyte(0x54); - addbyte(0xc5); - addbyte(cpu_state_offset(MM)); - addbyte(0x8b); /*MOV ECX, [ST_i64+4+EAX]*/ - addbyte(0x4c); - addbyte(0xc5); - addbyte(cpu_state_offset(MM)+4); - addbyte(0x8a); /*MOV AL, [tag+EAX]*/ - addbyte(0x44); - addbyte(0x05); - addbyte(cpu_state_offset(tag[0])); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); - addbyte(0x89); /*MOV [ST_i64+EBX], EDX*/ - addbyte(0x54); - addbyte(0xdd); - addbyte(cpu_state_offset(MM)); - addbyte(0x89); /*MOV [ST_i64+EBX+4], ECX*/ - addbyte(0x4c); - addbyte(0xdd); - addbyte(cpu_state_offset(MM)+4); + addbyte(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(0x07); + addbyte(0x8b); /*MOV EDX, [ST_i64+EAX]*/ + addbyte(0x54); + addbyte(0xc5); + addbyte(cpu_state_offset(MM)); + addbyte(0x8b); /*MOV ECX, [ST_i64+4+EAX]*/ + addbyte(0x4c); + addbyte(0xc5); + addbyte(cpu_state_offset(MM)+4); + addbyte(0x8a); /*MOV AL, [tag+EAX]*/ + addbyte(0x44); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x88); /*MOV [tag+EBX], AL*/ + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(0x89); /*MOV [ST_i64+EBX], EDX*/ + addbyte(0x54); + addbyte(0xdd); + addbyte(cpu_state_offset(MM)); + addbyte(0x89); /*MOV [ST_i64+EBX+4], ECX*/ + addbyte(0x4c); + addbyte(0xdd); + addbyte(cpu_state_offset(MM)+4); - addbyte(0x89); /*MOV [TOP], EBX*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [TOP], EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + } } static void FP_FST(int reg) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte(cpu_state_offset(TOP)); - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [tag+EAX]*/ - addbyte(0x5c); - addbyte(0x05); - addbyte(cpu_state_offset(tag[0])); - - if (reg) + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); + addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); } + else + { + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [tag+EAX]*/ + addbyte(0x5c); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); - addbyte(0xdd); /*FSTP [ST+EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); - addbyte(0x88); /*MOV [tag+EAX], BL*/ - addbyte(0x5c); - addbyte(0x05); - addbyte(cpu_state_offset(tag[0])); + if (reg) + { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } + + addbyte(0xdd); /*FSTP [ST+EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x88); /*MOV [tag+EAX], BL*/ + addbyte(0x5c); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + } } static void FP_FXCH(int reg) { - addbyte(0x8b); /*MOV EAX, [TOP]*/ - addbyte(0x45); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - addbyte(0x83); /*ADD EAX, reg*/ - addbyte(0xc0); - addbyte(reg); -//#if 0 - addbyte(0xdd); /*FLD [ST+EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - addbyte(0xdd); /*FLD [ST+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP [ST+EAX*8]*/ - addbyte(0x5c); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); -// addbyte(0xbe); /*MOVL ESI, tag*/ -// addlong((uintptr_t)cpu_state.tag); - addbyte(0x8a); /*MOV CL, tag[EAX]*/ - addbyte(0x4c); - addbyte(0x05); - addbyte(cpu_state_offset(tag[0])); - addbyte(0x8a); /*MOV DL, tag[EBX]*/ - addbyte(0x54); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); - addbyte(0x88); /*MOV tag[EBX], CL*/ - addbyte(0x4c); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); - addbyte(0x88); /*MOV tag[EAX], DL*/ - addbyte(0x54); - addbyte(0x05); - addbyte(cpu_state_offset(tag[0])); - addbyte(0xbe); /*MOVL ESI, ST_int64*/ - addlong((uintptr_t)cpu_state.MM); - addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]*/ - addbyte(0x0c); - addbyte(0xc6); - addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]*/ - addbyte(0x14); - addbyte(0xde); - addbyte(0x89); /*MOV ST_int64[EBX*8], ECX*/ - addbyte(0x0c); - addbyte(0xde); - addbyte(0x89); /*MOV ST_int64[EAX*8], EDX*/ - addbyte(0x14); - addbyte(0xc6); - addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]+4*/ - addbyte(0x4c); - addbyte(0xc6); - addbyte(0x04); - addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]+4*/ - addbyte(0x54); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOV ST_int64[EBX*8]+4, ECX*/ - addbyte(0x4c); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOV ST_int64[EAX*8]+4, EDX*/ - addbyte(0x54); - addbyte(0xc6); - addbyte(0x04); - reg = reg; -//#endif -#if 0 - addbyte(0xbe); /*MOVL ESI, ST*/ - addlong((uintptr_t)cpu_state.ST); - - addbyte(0x8b); /*MOVL EDX, [ESI+EBX*8]*/ - addbyte(0x14); - addbyte(0xde); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(0x07); - addbyte(0x8b); /*MOVL ECX, [ESI+EAX*8]*/ - addbyte(0x0c); - addbyte(0xc6); - addbyte(0x89); /*MOVL [ESI+EBX*8], ECX*/ - addbyte(0x0c); - addbyte(0xde); - addbyte(0x89); /*MOVL [ESI+EAX*8], EDX*/ - addbyte(0x14); - addbyte(0xc6); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0xf3); /*MOVQ XMM0, ST[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xf3); /*MOVQ XMM1, ST[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x4d); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0x66); /*MOVQ ST[reg][EBP], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + addbyte(0xf3); /*MOVQ XMM2, MM[0][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x55); + addbyte(cpu_state_offset(MM[cpu_state.TOP].q)); + addbyte(0x66); /*MOVQ ST[0][EBP], XMM1*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x4d); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0xf3); /*MOVQ XMM3, MM[reg][EBP]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x5d); + addbyte(cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x66); /*MOVQ MM[reg][EBP], XMM2*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x55); + addbyte(cpu_state_offset(MM[(cpu_state.TOP + reg) & 7].q)); + addbyte(0x8a); /*MOV AL, tag[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(0x66); /*MOVQ MM[0][EBP], XMM3*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x5d); + addbyte(cpu_state_offset(MM[cpu_state.TOP].q)); + addbyte(0x8a); /*MOV AH, tag[reg][EBP]*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP + reg) & 7])); + addbyte(0x88); /*MOV tag[0][EBP], AH*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + } + else + { + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); - addbyte(0x8b); /*MOVL ECX, [4+ESI+EAX*8]*/ - addbyte(0x4c); - addbyte(0xc6); - addbyte(0x04); - addbyte(0x8b); /*MOVL EDX, [4+ESI+EBX*8]*/ - addbyte(0x54); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOVL [4+ESI+EBX*8], ECX*/ - addbyte(0x4c); - addbyte(0xde); - addbyte(0x04); - addbyte(0x89); /*MOVL [4+ESI+EAX*8], EDX*/ - addbyte(0x54); - addbyte(0xc6); - addbyte(0x04); -#endif + addbyte(0xdd); /*FLD [ST+EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + addbyte(0xdd); /*FLD [ST+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP [ST+EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x8a); /*MOV CL, tag[EAX]*/ + addbyte(0x4c); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(0x8a); /*MOV DL, tag[EBX]*/ + addbyte(0x54); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(0x88); /*MOV tag[EBX], CL*/ + addbyte(0x4c); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(0x88); /*MOV tag[EAX], DL*/ + addbyte(0x54); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(0xbe); /*MOVL ESI, ST_int64*/ + addlong((uintptr_t)cpu_state.MM); + addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]*/ + addbyte(0x0c); + addbyte(0xc6); + addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]*/ + addbyte(0x14); + addbyte(0xde); + addbyte(0x89); /*MOV ST_int64[EBX*8], ECX*/ + addbyte(0x0c); + addbyte(0xde); + addbyte(0x89); /*MOV ST_int64[EAX*8], EDX*/ + addbyte(0x14); + addbyte(0xc6); + addbyte(0x8b); /*MOV ECX, ST_int64[EAX*8]+4*/ + addbyte(0x4c); + addbyte(0xc6); + addbyte(0x04); + addbyte(0x8b); /*MOV EDX, ST_int64[EBX*8]+4*/ + addbyte(0x54); + addbyte(0xde); + addbyte(0x04); + addbyte(0x89); /*MOV ST_int64[EBX*8]+4, ECX*/ + addbyte(0x4c); + addbyte(0xde); + addbyte(0x04); + addbyte(0x89); /*MOV ST_int64[EAX*8]+4, EDX*/ + addbyte(0x54); + addbyte(0xc6); + addbyte(0x04); + } } static void FP_LOAD_S() { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xd9); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0xd9); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + block_current = block_current; + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xd9); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + } } static void FP_LOAD_D() { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0xdd); /*FLD [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV ST[reg][EBP], EAX*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV ST[reg][EBP]+4, EDX*/ + addbyte(0x55); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7]) + 4); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0xdd); /*FLD [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + } } static void FP_LOAD_IW() { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xdf); /*FILDw [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0x66); /*TEST AX, AX*/ + addbyte(0x85); + addbyte(0xc0); + addbyte(0xdf); /*FILDw [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xdf); /*FILDw [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + } } static void FP_LOAD_IL() { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0xdb); /*FILDl [ESP]*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x0f); /*SETE [tag+EBX]*/ - addbyte(0x94); - addbyte(0x44); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0xdb); /*FILDl [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x0f); /*SETE tag[reg][EBP]*/ + addbyte(0x94); + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0xdb); /*FILDl [ESP]*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + } } static void FP_LOAD_IQ() { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x83); /*SUB EBX, 1*/ - addbyte(0xeb); - addbyte(1); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); - addbyte(0x89); /*MOV [ST_i64+EBX*8], EAX*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(MM)); - addbyte(0x09); /*OR EAX, EDX*/ - addbyte(0xd0); - addbyte(0x89); /*MOV [ST_i64+4+EBX*8], EDX*/ - addbyte(0x54); - addbyte(0xdd); - addbyte(cpu_state_offset(MM)+4); - addbyte(0x83); /*CMP EAX, 0*/ - addbyte(0xf8); - addbyte(0); - addbyte(0xdf); /*FILDl [ST_i64+EBX*8]*/ - addbyte(0x6c); - addbyte(0xdd); - addbyte(cpu_state_offset(MM)); - addbyte(0x0f); /*SETE AL*/ - addbyte(0x94); - addbyte(0xc0); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x0c); /*OR AL, TAG_UINT64*/ - addbyte(TAG_UINT64); - addbyte(0x89); /*MOV TOP, EBX*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x88); /*MOV [tag+EBX], AL*/ - addbyte(0x44); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV MM[reg][EBP], EAX*/ + addbyte(0x45); + addbyte(cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV MM[reg][EBP]+4, EDX*/ + addbyte(0x55); + addbyte(cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q) + 4); + addbyte(0x0f); /*SETE AL*/ + addbyte(0x94); + addbyte(0xc0); + addbyte(0xdf); /*FILDq MM[reg][EBP]*/ + addbyte(0x6d); + addbyte(cpu_state_offset(MM[(cpu_state.TOP - 1) & 7].q)); + addbyte(0x0c); /*OR AL, TAG_UINT64*/ + addbyte(TAG_UINT64); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP - 1) & 7); + addbyte(0x88); /*MOV tag[reg][EBP], AL*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[(cpu_state.TOP - 1) & 7])); + addbyte(0xdd); /*FSTP ST[reg][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[(cpu_state.TOP - 1) & 7])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(1); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x89); /*MOV [ST_i64+EBX*8], EAX*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(MM)); + addbyte(0x09); /*OR EAX, EDX*/ + addbyte(0xd0); + addbyte(0x89); /*MOV [ST_i64+4+EBX*8], EDX*/ + addbyte(0x54); + addbyte(0xdd); + addbyte(cpu_state_offset(MM)+4); + addbyte(0x83); /*CMP EAX, 0*/ + addbyte(0xf8); + addbyte(0); + addbyte(0xdf); /*FILDl [ST_i64+EBX*8]*/ + addbyte(0x6c); + addbyte(0xdd); + addbyte(cpu_state_offset(MM)); + addbyte(0x0f); /*SETE AL*/ + addbyte(0x94); + addbyte(0xc0); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x0c); /*OR AL, TAG_UINT64*/ + addbyte(TAG_UINT64); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x88); /*MOV [tag+EBX], AL*/ + addbyte(0x44); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + } } static int FP_LOAD_REG(int reg) { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - if (reg) + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); + addbyte(0xdd); /*FLD ST[reg][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + if (reg) + { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); addbyte(0xd9); /*FSTP [ESP]*/ addbyte(0x1c); addbyte(0x24); @@ -2271,22 +2486,31 @@ static int FP_LOAD_REG(int reg) static void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - if (reg) + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { - addbyte(0x83); /*ADD EBX, reg*/ - addbyte(0xc3); - addbyte(reg); - addbyte(0x83); /*AND EBX, 7*/ - addbyte(0xe3); - addbyte(7); + addbyte(0xdd); /*FLD ST[reg][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + reg) & 7])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + if (reg) + { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc3); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + } + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); } - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); addbyte(0xdd); /*FSTP [ESP]*/ addbyte(0x1c); addbyte(0x24); @@ -2542,21 +2766,35 @@ static void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) static void FP_POP() { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte(cpu_state_offset(TOP)); - addbyte(0xc6); /*MOVB tag[EAX], 3*/ - addbyte(0x44); - addbyte(0x05); - addbyte(cpu_state_offset(tag[0])); - addbyte(3); - addbyte(0x04); /*ADD AL, 1*/ - addbyte(1); - addbyte(0x24); /*AND AL, 7*/ - addbyte(7); - addbyte(0x88); /*MOV TOP, AL*/ - addbyte(0x45); - addbyte(cpu_state_offset(TOP)); + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0xc6); /*MOVB tag[0][EBP], 3*/ + addbyte(0x45); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(3); + addbyte(0xc6); /*MOVB TOP[EBP], (TOP-1) & 7*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte((cpu_state.TOP + 1) & 7); + } + else + { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ + addbyte(0x44); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(3); + addbyte(0x04); /*ADD AL, 1*/ + addbyte(1); + addbyte(0x24); /*AND AL, 7*/ + addbyte(7); + addbyte(0x88); /*MOV TOP, AL*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + } } #define FPU_ADD 0x00 @@ -2568,340 +2806,33 @@ static void FP_POP() static void FP_OP_S(int op) { - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xd8); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); -} -static void FP_OP_D(int op) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { - addbyte(0x9b); /*FSTCW [ESP+8]*/ - addbyte(0xd9); - addbyte(0x7c); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); addbyte(0x24); - addbyte(0x08); - addbyte(0x66); /*MOV AX, [ESP+8]*/ - addbyte(0x8b); - addbyte(0x44); + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(~TAG_UINT64); + addbyte(0xd8); /*FADD [ESP]*/ + addbyte(0x04 | op); addbyte(0x24); - addbyte(0x08); - addbyte(0x66); /*AND AX, ~(3 << 10)*/ - addbyte(0x25); - addword(~(3 << 10)); - addbyte(0x66); /*OR AX, npxc & (3 << 10)*/ - addbyte(0x0d); - addword(cpu_state.npxc & (3 << 10)); - addbyte(0x66); /*MOV [ESP+12], AX*/ - addbyte(0x89); - addbyte(0x44); - addbyte(0x24); - addbyte(0x0c); - addbyte(0xd9); /*FLDCW [ESP+12]*/ - addbyte(0x6c); - addbyte(0x24); - addbyte(0x0c); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); } - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) + else { - addbyte(0xd9); /*FLDCW [ESP+8]*/ - addbyte(0x6c); + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); addbyte(0x24); - addbyte(0x08); - } -} -static void FP_OP_IW(int op) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xde); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); -} -static void FP_OP_IL(int op) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xda); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); -} -static void FP_OP_IQ(int op) -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x1d); - addbyte(cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD [ESP]*/ - addbyte(0x04 | op); - addbyte(0x24); - addbyte(0xdd); /*FSTP [ST+EBX*8]*/ - addbyte(0x5c); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); -} - -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) - -static void FP_COMPARE_S() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte(cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xd8); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte(cpu_state_offset(npxs) + 1); -} -static void FP_COMPARE_D() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0x89); /*MOV [ESP+4], EDX*/ - addbyte(0x54); - addbyte(0x24); - addbyte(0x04); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte(cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xdc); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte(cpu_state_offset(npxs) + 1); -} -static void FP_COMPARE_IW() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte(cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xde); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte(cpu_state_offset(npxs) + 1); -} -static void FP_COMPARE_IL() -{ - addbyte(0x8b); /*MOV EBX, TOP*/ - addbyte(0x5d); - addbyte(cpu_state_offset(TOP)); - addbyte(0x89); /*MOV [ESP], EAX*/ - addbyte(0x04); - addbyte(0x24); - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0x8a); /*MOV BL, [npxs+1]*/ - addbyte(0x5d); - addbyte(cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ - addbyte(0xe3); - addbyte((~(C0|C2|C3)) >> 8); - addbyte(0xda); /*FCOMP [ESP]*/ - addbyte(0x04 | 0x18); - addbyte(0x24); - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR BL, AH*/ - addbyte(0xe3); - addbyte(0x88); /*MOV [npxs+1], BL*/ - addbyte(0x5d); - addbyte(cpu_state_offset(npxs) + 1); -} - -static void FP_OP_REG(int op, int dst, int src) -{ - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte(cpu_state_offset(TOP)); -// addbyte(0xbe); /*MOVL ESI, ST*/ -// addlong((uintptr_t)cpu_state.ST); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) - { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ - addbyte(0xe0); - addbyte(7); - } - - if (src) - { addbyte(0xdd); /*FLD ST[EBX*8]*/ addbyte(0x44); addbyte(0xdd); @@ -2911,98 +2842,741 @@ static void FP_OP_REG(int op, int dst, int src) addbyte(0x1d); addbyte(cpu_state_offset(tag[0])); addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD ST[EAX*8]*/ - addbyte(0x44 | op); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP ST[EBX*8]*/ + addbyte(0xd8); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ addbyte(0x5c); addbyte(0xdd); addbyte(cpu_state_offset(ST)); } +} +static void FP_OP_D(int op) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) + { + addbyte(0x9b); /*FSTCW [ESP+8]*/ + addbyte(0xd9); + addbyte(0x7c); + addbyte(0x24); + addbyte(0x08); + addbyte(0x66); /*MOV AX, [ESP+8]*/ + addbyte(0x8b); + addbyte(0x44); + addbyte(0x24); + addbyte(0x08); + addbyte(0x66); /*AND AX, ~(3 << 10)*/ + addbyte(0x25); + addword(~(3 << 10)); + addbyte(0x66); /*OR AX, npxc & (3 << 10)*/ + addbyte(0x0d); + addword(cpu_state.npxc & (3 << 10)); + addbyte(0x66); /*MOV [ESP+12], AX*/ + addbyte(0x89); + addbyte(0x44); + addbyte(0x24); + addbyte(0x0c); + addbyte(0xd9); /*FLDCW [ESP+12]*/ + addbyte(0x6c); + addbyte(0x24); + addbyte(0x0c); + } + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(~TAG_UINT64); + addbyte(0xdc); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) + { + addbyte(0xd9); /*FLDCW [ESP+8]*/ + addbyte(0x6c); + addbyte(0x24); + addbyte(0x08); + } + } else { - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) + { + addbyte(0x9b); /*FSTCW [ESP+8]*/ + addbyte(0xd9); + addbyte(0x7c); + addbyte(0x24); + addbyte(0x08); + addbyte(0x66); /*MOV AX, [ESP+8]*/ + addbyte(0x8b); + addbyte(0x44); + addbyte(0x24); + addbyte(0x08); + addbyte(0x66); /*AND AX, ~(3 << 10)*/ + addbyte(0x25); + addword(~(3 << 10)); + addbyte(0x66); /*OR AX, npxc & (3 << 10)*/ + addbyte(0x0d); + addword(cpu_state.npxc & (3 << 10)); + addbyte(0x66); /*MOV [ESP+12], AX*/ + addbyte(0x89); + addbyte(0x44); + addbyte(0x24); + addbyte(0x0c); + addbyte(0xd9); /*FLDCW [ESP+12]*/ + addbyte(0x6c); + addbyte(0x24); + addbyte(0x0c); + } + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[EBX*8]*/ addbyte(0x44); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); - addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ - addbyte(0x64); - addbyte(0x05); - addbyte(cpu_state_offset(tag[0])); - addbyte(~TAG_UINT64); - addbyte(0xdc); /*FADD ST[EBX*8]*/ - addbyte(0x44 | op); addbyte(0xdd); addbyte(cpu_state_offset(ST)); - addbyte(0xdd); /*FSTP ST[EAX*8]*/ + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xdc); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ addbyte(0x5c); - addbyte(0xc5); + addbyte(0xdd); addbyte(cpu_state_offset(ST)); + if (((cpu_state.npxc >> 10) & 3) && op == FPU_ADD) + { + addbyte(0xd9); /*FLDCW [ESP+8]*/ + addbyte(0x6c); + addbyte(0x24); + addbyte(0x08); + } + } +} +static void FP_OP_IW(int op) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(~TAG_UINT64); + addbyte(0xde); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[0][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xde); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + } +} +static void FP_OP_IL(int op) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(~TAG_UINT64); + addbyte(0xda); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[0][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xda); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + } +} +static void FP_OP_IQ(int op) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x80); /*AND tag[0][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[cpu_state.TOP])); + addbyte(~TAG_UINT64); + addbyte(0xdc); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP ST[0][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xdc); /*FADD [ESP]*/ + addbyte(0x04 | op); + addbyte(0x24); + addbyte(0xdd); /*FSTP [ST+EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + } +} + +#define C0 (1<<8) +#define C1 (1<<9) +#define C2 (1<<10) +#define C3 (1<<14) + +static void FP_COMPARE_S() +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xd8); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xd8); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + } +} +static void FP_COMPARE_D() +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xdc); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0x89); /*MOV [ESP+4], EDX*/ + addbyte(0x54); + addbyte(0x24); + addbyte(0x04); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xdc); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + } +} +static void FP_COMPARE_IW() +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x66); /*MOV [ESP], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xde); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xde); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + } +} +static void FP_COMPARE_IL() +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[0][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[cpu_state.TOP])); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xda); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + } + else + { + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x5d); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x8a); /*MOV BL, [npxs+1]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ + addbyte(0xe3); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xda); /*FCOMP [ESP]*/ + addbyte(0x04 | 0x18); + addbyte(0x24); + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR BL, AH*/ + addbyte(0xe3); + addbyte(0x88); /*MOV [npxs+1], BL*/ + addbyte(0x5d); + addbyte(cpu_state_offset(npxs) + 1); + } +} + +static void FP_OP_REG(int op, int dst, int src) +{ + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) + { + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + addbyte(0xdc); /*FADD ST[src][EBP]*/ + addbyte(0x45 | op); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); + addbyte(0x80); /*AND tag[dst][EBP], ~TAG_UINT64*/ + addbyte(0x65); + addbyte(cpu_state_offset(tag[(cpu_state.TOP + dst) & 7])); + addbyte(~TAG_UINT64); + addbyte(0xdd); /*FSTP ST[dst][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + } + else + { + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (src || dst) + { + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(src ? src : dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } + + if (src) + { + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EBX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x1d); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xdc); /*FADD ST[EAX*8]*/ + addbyte(0x44 | op); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP ST[EBX*8]*/ + addbyte(0x5c); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + } + else + { + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0x64); + addbyte(0x05); + addbyte(cpu_state_offset(tag[0])); + addbyte(~TAG_UINT64); + addbyte(0xdc); /*FADD ST[EBX*8]*/ + addbyte(0x44 | op); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0xdd); /*FSTP ST[EAX*8]*/ + addbyte(0x5c); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + } } } static void FP_COMPARE_REG(int dst, int src) { - addbyte(0x8b); /*MOV EAX, TOP*/ - addbyte(0x45); - addbyte(cpu_state_offset(TOP)); -// addbyte(0xbe); /*MOVL ESI, ST*/ -// addlong((uintptr_t)cpu_state.ST); - addbyte(0x89); /*MOV EBX, EAX*/ - addbyte(0xc3); - if (src || dst) + if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { - addbyte(0x83); /*ADD EAX, 1*/ - addbyte(0xc0); - addbyte(src ? src : dst); - addbyte(0x83); /*AND EAX, 7*/ + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x4d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0xdd); /*FLD ST[dst][EBP]*/ + addbyte(0x45); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0xdc); /*FCOMP ST[src][EBP]*/ + addbyte(0x5d); + addbyte(cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); + addbyte(0xdf); /*FSTSW AX*/ addbyte(0xe0); - addbyte(7); - } - - addbyte(0x8a); /*MOV CL, [npxs+1]*/ - addbyte(0x4d); - addbyte(cpu_state_offset(npxs) + 1); - addbyte(0xdb); /*FCLEX*/ - addbyte(0xe2); - addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ - addbyte(0xe1); - addbyte((~(C0|C2|C3)) >> 8); - - if (src) - { - addbyte(0xdd); /*FLD ST[EBX*8]*/ - addbyte(0x44); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - addbyte(0xdc); /*FCOMP ST[EAX*8]*/ - addbyte(0x44 | 0x18); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR CL, AH*/ + addbyte(0xe1); + addbyte(0x88); /*MOV [npxs+1], CL*/ + addbyte(0x4d); + addbyte(cpu_state_offset(npxs) + 1); } else { - addbyte(0xdd); /*FLD [ESI+EAX*8]*/ - addbyte(0x44); - addbyte(0xc5); - addbyte(cpu_state_offset(ST)); - addbyte(0xdc); /*FCOMP ST[EBX*8]*/ - addbyte(0x44 | 0x18); - addbyte(0xdd); - addbyte(cpu_state_offset(ST)); - } + addbyte(0x8b); /*MOV EAX, TOP*/ + addbyte(0x45); + addbyte(cpu_state_offset(TOP)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (src || dst) + { + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(src ? src : dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } - addbyte(0xdf); /*FSTSW AX*/ - addbyte(0xe0); - addbyte(0x80); /*AND AH, (C0|C2|C3)*/ - addbyte(0xe4); - addbyte((C0|C2|C3) >> 8); - addbyte(0x08); /*OR CL, AH*/ - addbyte(0xe1); - addbyte(0x88); /*MOV [npxs+1], CL*/ - addbyte(0x4d); - addbyte(cpu_state_offset(npxs) + 1); + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x4d); + addbyte(cpu_state_offset(npxs) + 1); + addbyte(0xdb); /*FCLEX*/ + addbyte(0xe2); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0|C2|C3)) >> 8); + + if (src) + { + addbyte(0xdd); /*FLD ST[EBX*8]*/ + addbyte(0x44); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + addbyte(0xdc); /*FCOMP ST[EAX*8]*/ + addbyte(0x44 | 0x18); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + } + else + { + addbyte(0xdd); /*FLD [ESI+EAX*8]*/ + addbyte(0x44); + addbyte(0xc5); + addbyte(cpu_state_offset(ST)); + addbyte(0xdc); /*FCOMP ST[EBX*8]*/ + addbyte(0x44 | 0x18); + addbyte(0xdd); + addbyte(cpu_state_offset(ST)); + } + + addbyte(0xdf); /*FSTSW AX*/ + addbyte(0xe0); + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR CL, AH*/ + addbyte(0xe1); + addbyte(0x88); /*MOV [npxs+1], CL*/ + addbyte(0x4d); + addbyte(cpu_state_offset(npxs) + 1); + } } static int ZERO_EXTEND_W_B(int reg) diff --git a/src/codegen_x86-64.c b/src/codegen_x86-64.c index c1de9f781..7673a08e4 100644 --- a/src/codegen_x86-64.c +++ b/src/codegen_x86-64.c @@ -281,7 +281,8 @@ void codegen_block_init(uint32_t phys_addr) block->next = block->prev = NULL; block->next_2 = block->prev_2 = NULL; block->page_mask = 0; - + block->flags = 0; + block->was_recompiled = 0; recomp_page = block->phys & ~0xfff; @@ -1005,6 +1006,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xd9: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; @@ -1013,6 +1015,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xda: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; @@ -1021,6 +1024,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdb: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; @@ -1029,6 +1033,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdc: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; @@ -1038,6 +1043,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdd: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; @@ -1046,6 +1052,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xde: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; @@ -1054,6 +1061,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdf: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; @@ -1062,6 +1070,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xf0: /*LOCK*/ diff --git a/src/codegen_x86.c b/src/codegen_x86.c index 6bfa57020..a0288fcd5 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -281,6 +281,7 @@ void codegen_block_init(uint32_t phys_addr) block->next = block->prev = NULL; block->next_2 = block->prev_2 = NULL; block->page_mask = 0; + block->flags = CODEBLOCK_STATIC_TOP; block->was_recompiled = 0; @@ -359,6 +360,7 @@ void codegen_block_start_recompile(codeblock_t *block) _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1; + block->TOP = cpu_state.TOP; block->was_recompiled = 1; } @@ -484,6 +486,9 @@ void codegen_block_end_recompile(codeblock_t *block) codegen_block_generate_end_mask(); add_to_block_list(block); // pclog("End block %i\n", block_num); + + if (!(block->flags & CODEBLOCK_HAS_FPU)) + block->flags &= ~CODEBLOCK_STATIC_TOP; } void codegen_flush() @@ -821,6 +826,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xd9: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; @@ -829,6 +835,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xda: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; @@ -837,6 +844,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdb: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; @@ -845,6 +853,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdc: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; @@ -854,6 +863,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdd: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; @@ -862,6 +872,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xde: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; @@ -870,6 +881,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xdf: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; @@ -878,6 +890,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t over = 1; pc_off = -1; test_modrm = 0; + block->flags |= CODEBLOCK_HAS_FPU; break; case 0xf0: /*LOCK*/ diff --git a/src/disc_86f.c b/src/disc_86f.c index 28b855487..b0bfa6249 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -88,8 +88,12 @@ static struct crc_t track_crc; uint8_t track_byte; uint8_t track_index; + uint8_t track_fuzzy; + uint8_t track_data_byte; uint8_t old_track_byte; uint8_t old_track_index; + uint8_t old_track_fuzzy; + uint8_t old_track_data_byte; uint8_t cur_track; uint8_t side_flag_bytes; } d86f[2]; @@ -857,6 +861,15 @@ int d86f_can_read_address(int drive) return temp; } +int d86f_should_write_am(int drive) +{ + int temp; + temp = (d86f[drive].state == STATE_WRITE_FIND_SECTOR); + temp = temp && (d86f[drive].req_sector.dword == d86f[drive].last_sector.dword); + temp = temp && d86f_can_read_address(drive); + return temp; +} + int d86f_can_format(int drive) { int temp; @@ -943,20 +956,19 @@ void d86f_poll_write_crc(int drive, int side) { if (d86f[drive].state != STATE_FORMAT) return; d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos; - if (d86f[drive].id_pos) - { - d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].calc_crc.bytes[1]; - } - else - { - d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].calc_crc.bytes[0]; - } + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = d86f[drive].calc_crc.bytes[d86f[drive].id_pos ^ 1]; } void d86f_poll_advancebyte(int drive, int side) { d86f[drive].old_track_byte = d86f[drive].track_byte; d86f[drive].old_track_index = d86f[drive].track_index; + d86f[drive].old_track_data_byte = d86f[drive].track_data_byte; + + if (d86f[drive].version == 0x0114) + { + d86f[drive].old_track_fuzzy = d86f[drive].track_fuzzy; + } d86f[drive].track_pos++; d86f[drive].track_pos %= d86f_get_raw_size(drive); @@ -965,11 +977,22 @@ void d86f_poll_advancebyte(int drive, int side) { d86f[drive].track_byte = d86f[drive].track_layout[side][d86f[drive].track_pos] & ~BYTE_INDEX_HOLE; d86f[drive].track_index = d86f[drive].track_layout[side][d86f[drive].track_pos] & BYTE_INDEX_HOLE; + d86f[drive].track_data_byte = d86f[drive].track_data[side][d86f[drive].track_pos]; } else if (d86f[drive].version == 0x0114) { d86f[drive].track_byte = d86f[drive].track_layout[side][d86f[drive].track_pos] & ~BYTE_IS_FUZZY; d86f[drive].track_index = (d86f[drive].track_pos == d86f[drive].index_hole_pos[side]); + d86f[drive].track_fuzzy = d86f[drive].track_layout[side][d86f[drive].track_pos] & BYTE_IS_FUZZY; + + if (d86f[drive].track_fuzzy) + { + d86f[drive].track_data_byte = disc_random_generate(); + } + else + { + d86f[drive].track_data_byte = d86f[drive].track_data[side][d86f[drive].track_pos]; + } } } @@ -1006,16 +1029,6 @@ void d86f_poll_finish(int drive, int side) d86f[drive].last_sector.dword = 0xFFFFFFFF; } -uint8_t d86f_poll_data(int drive, int side) -{ - uint8_t ret = d86f[drive].track_data[side][d86f[drive].track_pos]; - if ((d86f[drive].version == 0x0114) && (d86f[drive].track_layout[side][d86f[drive].track_pos] & BYTE_IS_FUZZY)) - { - ret = disc_random_generate(); - } - return ret; -} - int d86f_mark_index_hole(int drive) { int temp = (d86f[drive].version == 0x0100); @@ -1023,6 +1036,13 @@ int d86f_mark_index_hole(int drive) return temp; } +void d86f_poll_write(int drive, int side, uint8_t data, uint8_t type) +{ + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = data; + d86f[drive].track_layout[side][d86f[drive].track_pos] = type; + if (!d86f[drive].track_pos && d86f_mark_index_hole(drive)) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE; +} + void d86f_poll_readwrite(int drive, int side) { int data; @@ -1031,7 +1051,7 @@ void d86f_poll_readwrite(int drive, int side) if (d86f_read_state_data(drive)) { max_len = d86f_data_size(drive); - data = d86f_poll_data(drive, side); + data = d86f[drive].track_data_byte; if (d86f[drive].datac < d86f_get_data_len(drive)) { fdc_data(data); @@ -1055,25 +1075,21 @@ void d86f_poll_readwrite(int drive, int side) } if (!disable_write) { - d86f[drive].track_data[side][d86f[drive].track_pos] = data; - d86f[drive].track_layout[side][d86f[drive].track_pos] = BYTE_DATA; - if (!d86f[drive].track_pos && d86f_mark_index_hole(drive)) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE; + d86f_poll_write(drive, side, data, BYTE_DATA); } - d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]); + d86f_calccrc(drive, d86f[drive].track_data_byte); } else if (d86f_read_state_crc(drive)) { max_len = 2; - d86f[drive].track_crc.bytes[d86f[drive].datac] = d86f_poll_data(drive, side); + d86f[drive].track_crc.bytes[d86f[drive].datac ^ 1] = d86f[drive].track_data_byte; } else if (d86f[drive].state == STATE_WRITE_SECTOR_CRC) { max_len = 2; if (!disable_write) { - d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].calc_crc.bytes[d86f[drive].datac]; - d86f[drive].track_layout[side][d86f[drive].track_pos] = BYTE_DATA_CRC; - if (!d86f[drive].track_pos) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE; + d86f_poll_write(drive, side, d86f[drive].calc_crc.bytes[d86f[drive].datac ^ 1], BYTE_DATA_CRC); } } else if (d86f_read_state_gap3(drive)) @@ -1084,6 +1100,7 @@ void d86f_poll_readwrite(int drive, int side) d86f_poll_finish(drive, side); if (d86f[drive].track_crc.word != d86f[drive].calc_crc.word) { + // pclog("d86f_poll(): Data CRC error (%i %i %i %i) (%04X %04X)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, d86f[drive].track_crc.word, d86f[drive].calc_crc.word); fdc_finishread(); fdc_datacrcerror(); } @@ -1099,7 +1116,11 @@ void d86f_poll_readwrite(int drive, int side) max_len = fdc_get_gap(); if (d86f[drive].datac == (fdc_get_gap() - 1)) { - if (!disable_write) d86f_writeback(drive); + if (!disable_write) + { + d86f_poll_write(drive, side, fdc_is_mfm() ? 0x4E : 0xFF, BYTE_GAP3); + d86f_writeback(drive); + } d86f_poll_finish(drive, side); fdc_sector_finishread(drive); return; @@ -1108,9 +1129,7 @@ void d86f_poll_readwrite(int drive, int side) { if (!disable_write) { - d86f[drive].track_data[side][d86f[drive].track_pos] = fdc_is_mfm() ? 0x4E : 0xFF; - d86f[drive].track_layout[side][d86f[drive].track_pos] = BYTE_GAP3; - if (!d86f[drive].track_pos) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE; + d86f_poll_write(drive, side, fdc_is_mfm() ? 0x4E : 0xFF, BYTE_GAP3); } } } @@ -1138,35 +1157,38 @@ void d86f_poll_find_nf(int drive, int side) switch(d86f[drive].track_byte) { - case BYTE_IDAM: - d86f[drive].calc_crc.word = fdc_is_mfm() ? 0xcdb4 : 0xffff; - // pclog("CRC reset: %02X\n", d86f[drive].track_byte); - d86f_calccrc(drive, d86f_poll_data(drive, side)); + case BYTE_DATAAM_SYNC: + if (d86f_should_write_am(drive)) + { + d86f_poll_write(drive, side, 0xA1, BYTE_DATAAM_SYNC); + } + + case BYTE_IDAM_SYNC: + if (d86f_is_mfm(drive)) + { + d86f_calccrc(drive, d86f[drive].track_data_byte); + } break; case BYTE_DATAAM: - d86f[drive].calc_crc.word = fdc_is_mfm() ? 0xcdb4 : 0xffff; - // pclog("CRC reset: %02X\n", d86f[drive].track_byte); - - if ((d86f[drive].state == STATE_WRITE_FIND_SECTOR) && (d86f[drive].req_sector.dword == d86f[drive].last_sector.dword) && d86f_can_read_address(drive)) + if (d86f_should_write_am(drive)) { - d86f[drive].track_data[side][d86f[drive].track_pos] = 0xFB; - if (d86f[drive].version == 0x0114) - { - d86f[drive].track_layout[side][d86f[drive].track_pos] &= ~BYTE_IS_FUZZY; - } + d86f_poll_write(drive, side, 0xFB, BYTE_DATAAM); } - d86f_calccrc(drive, d86f_poll_data(drive, side)); + + case BYTE_IDAM: + d86f_calccrc(drive, d86f[drive].track_data_byte); break; + case BYTE_ID: d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos; - data = d86f_poll_data(drive, side); + data = d86f[drive].track_data_byte; d86f[drive].rw_sector_id.byte_array[d86f[drive].id_pos] = data; d86f_calccrc(drive, data); break; case BYTE_ID_CRC: d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos; - d86f[drive].track_crc.bytes[d86f[drive].id_pos] = d86f_poll_data(drive, side); + d86f[drive].track_crc.bytes[d86f[drive].id_pos ^ 1] = d86f[drive].track_data_byte; break; } @@ -1180,19 +1202,36 @@ void d86f_poll_find_nf(int drive, int side) switch(d86f[drive].track_byte) { + case BYTE_IDAM_SYNC: + case BYTE_DATAAM_SYNC: + if (d86f_is_mfm(drive)) + { + d86f[drive].calc_crc.word = 0xffff; + } + break; + case BYTE_IDAM: + case BYTE_DATAAM: + if (!d86f_is_mfm(drive)) + { + d86f[drive].calc_crc.word = 0xffff; + } + break; case BYTE_GAP2: if (d86f_can_read_address(drive)) { - if (((d86f[drive].req_sector.dword == d86f[drive].rw_sector_id.dword) || (d86f[drive].state == STATE_READ_FIND_ADDRESS)) && d86f_can_read_address(drive)) + if ((d86f[drive].req_sector.dword == d86f[drive].rw_sector_id.dword) || (d86f[drive].state == STATE_READ_FIND_ADDRESS)) { if (d86f[drive].track_crc.word != d86f[drive].calc_crc.word) { - // pclog("d86f_poll(): Header CRC error (%i %i %i %i)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n); - fdc_finishread(); - fdc_headercrcerror(); - d86f[drive].state = STATE_IDLE; - d86f[drive].index_count = 0; - return; + if (d86f[drive].state != STATE_READ_FIND_ADDRESS) + { + // pclog("d86f_poll(): Header CRC error (%i %i %i %i) (%04X %04X)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, d86f[drive].track_crc.word, d86f[drive].calc_crc.word); + fdc_finishread(); + fdc_headercrcerror(); + d86f[drive].state = STATE_IDLE; + d86f[drive].index_count = 0; + return; + } } else { @@ -1203,7 +1242,7 @@ void d86f_poll_find_nf(int drive, int side) if ((d86f[drive].state == STATE_READ_FIND_ADDRESS) && (d86f[drive].last_sector.dword != 0xFFFFFFFF)) { - // pclog("Reading sector ID...\n"); + // pclog("Reading sector ID (%i %i %i %i)...\n", d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); fdc_sectorid(d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n, 0, 0); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; @@ -1240,49 +1279,29 @@ void d86f_poll_find_format(int drive, int side) { if (!(d86f_can_format(drive))) { - if (d86f_can_read_address(drive)) - { - // pclog("d86f_poll(): Disk is write protected or attempting to format wrong number of sectors per track\n"); - fdc_writeprotect(); - } - else - { - // pclog("d86f_poll(): Unable to format at the requested density or bitcell period\n"); - fdc_notfound(); - } + fdc_notfound(); d86f_poll_reset(drive, side); d86f_poll_advancebyte(drive, side); return; } - if (d86f[drive].track_index && d86f_can_read_address(drive)) - { - // pclog("Index hole hit, formatting track...\n"); - d86f[drive].state = STATE_FORMAT; - d86f_poll_advancebyte(drive, side); - return; - } - d86f_poll_advancebyte(drive, side); if (d86f_poll_check_notfound(drive)) return; + + if (d86f[drive].track_index) + { + // pclog("Index hole hit, formatting track...\n"); + d86f[drive].state = STATE_FORMAT; + // d86f_poll_advancebyte(drive, side); + return; + } } void d86f_poll_format(int drive, int side) { int data; - if (d86f[drive].track_index) - { - // pclog("Index hole hit again, format finished\n"); - d86f[drive].state = STATE_IDLE; - if (!disable_write) d86f_writeback(drive); - fdc_sector_finishread(drive); - d86f[drive].index_count = 0; - d86f_poll_advancebyte(drive, side); - return; - } - switch(d86f[drive].track_byte) { case BYTE_GAP0: @@ -1290,74 +1309,103 @@ void d86f_poll_format(int drive, int side) case BYTE_GAP2: case BYTE_GAP3: case BYTE_GAP4: - if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = fdc_is_mfm() ? 0x4E : 0xFF; + if (!disable_write) + { + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = fdc_is_mfm() ? 0x4E : 0xFF; + } break; case BYTE_IAM_SYNC: - if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0xC2; + if (!disable_write) + { + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = 0xC2; + } break; case BYTE_IAM: - if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0xFC; + if (!disable_write) + { + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = 0xFC; + } break; case BYTE_ID_SYNC: d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos; - if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0; - if (d86f[drive].id_pos > 3) break; + if (d86f[drive].id_pos > 3) + { + break; + } data = fdc_getdata(0); if ((data == -1) && (d86f[drive].id_pos < 3)) { data = 0; } d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos] = data & 0xff; - d86f_calccrc(drive, d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos]); // pclog("format_sector_id[%i] = %i\n", cur_id_pos, d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos]); if (d86f[drive].id_pos == 3) { fdc_stop_id_request(); // pclog("Formatting sector: %08X...\n", d86f[drive].format_sector_id.dword); } - break; case BYTE_I_SYNC: case BYTE_DATA_SYNC: - if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0; + if (!disable_write) + { + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = 0; + } break; case BYTE_IDAM_SYNC: case BYTE_DATAAM_SYNC: - if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0xA1; + if (!disable_write) + { + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = 0xA1; + } + if (d86f_is_mfm(drive)) + { + d86f_calccrc(drive, d86f[drive].track_data_byte); + } break; case BYTE_IDAM: case BYTE_DATAAM: - d86f[drive].calc_crc.word = fdc_is_mfm() ? 0xcdb4 : 0xffff; // pclog("CRC reset: %02X\n", d86f[drive].track_byte); - if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = (d86f[drive].track_byte == BYTE_IDAM) ? 0xFE : 0xFB; - d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]); + if (!disable_write) + { + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = (d86f[drive].track_byte == BYTE_IDAM) ? 0xFE : 0xFB; + } + d86f_calccrc(drive, d86f[drive].track_data_byte); break; case BYTE_ID: d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos; if (!disable_write) { - d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos]; + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos]; } - d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]); + d86f_calccrc(drive, d86f[drive].track_data_byte); break; case BYTE_DATA: if (!disable_write) { - d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].fill; - d86f_calccrc(drive, d86f[drive].fill); + d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].track_data_byte = d86f[drive].fill; } + d86f_calccrc(drive, d86f[drive].track_data_byte); break; case BYTE_ID_CRC: - d86f_poll_write_crc(drive, side); - break; case BYTE_DATA_CRC: - d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos; d86f_poll_write_crc(drive, side); break; } d86f_poll_advancebyte(drive, side); + if (d86f[drive].track_index) + { + // pclog("Index hole hit again, format finished\n"); + d86f[drive].state = STATE_IDLE; + if (!disable_write) d86f_writeback(drive); + fdc_sector_finishread(drive); + d86f[drive].index_count = 0; + // d86f_poll_advancebyte(drive, side); + return; + } + if (d86f[drive].track_byte != d86f[drive].old_track_byte) { // pclog("Track byte: %02X, old: %02X\n", track_byte, old_track_byte); @@ -1365,6 +1413,20 @@ void d86f_poll_format(int drive, int side) switch(d86f[drive].track_byte & ~BYTE_INDEX_HOLE) { + case BYTE_IDAM: + case BYTE_DATAAM: + if (!d86f_is_mfm(drive)) + { + d86f[drive].calc_crc.word = 0xffff; + } + break; + case BYTE_IDAM_SYNC: + case BYTE_DATAAM_SYNC: + if (d86f_is_mfm(drive)) + { + d86f[drive].calc_crc.word = 0xffff; + } + break; case BYTE_ID_SYNC: // pclog("Requesting next sector ID...\n"); fdc_request_next_sector_id(); diff --git a/src/fdc.c b/src/fdc.c index 212de678b..162a39079 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -70,6 +70,8 @@ typedef struct FDC int gap, dtl; int format_sectors; + + int max_track; } FDC; static FDC fdc; @@ -248,12 +250,24 @@ static void fdc_watchdog_poll(void *p) int bit_rate = 250; +static void fdc_rate(int drive); + void fdc_update_is_nsc(int is_nsc) { + int old_is_nsc = fdc.is_nsc; fdc.is_nsc = is_nsc; + if (old_is_nsc != is_nsc) + { + fdc.densel_force = fdc.densel_force ^ 3; + } + fdc_rate(0); + fdc_rate(1); } -static void fdc_rate(int drive); +void fdc_update_max_track(int max_track) +{ + fdc.max_track = max_track; +} void fdc_update_enh_mode(int enh_mode) { @@ -291,6 +305,11 @@ void fdc_update_densel_polarity(int densel_polarity) fdc_rate(1); } +uint8_t fdc_get_densel_polarity() +{ + return fdc.densel_polarity; +} + void fdc_update_densel_force(int densel_force) { fdc.densel_force = densel_force; @@ -774,9 +793,14 @@ bad_command: fdc_notfound(); else { - fdc_seek(fdc.drive, -79); + fdc_seek(fdc.drive, -fdc.max_track); + } + disctime = fdc.max_track * 10 * TIMER_USEC; + fdc.st0 &= 0x30; + if (!fdd_track0(fdc.drive)) + { + fdc.st0 |= 0x30; } - disctime = 790 * TIMER_USEC; break; case 0x0d: /*Format*/ @@ -815,6 +839,7 @@ bad_command: fdc_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); } disctime = 790 * TIMER_USEC; + fdc.st0 &= 0x30; break; case 10: /*Read sector ID*/ @@ -952,6 +977,37 @@ uint8_t fdc_read(uint16_t addr, void *priv) return temp; } +void fdc_poll_readwrite_finish() +{ + fdc.inread = 0; + discint=-2; + fdc_int(); + fdc.stat=0xD0; + fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; + fdc.res[5]=fdc.res[6]=0; + fdc.res[7]=fdc.rw_track; + fdc.res[8]=fdc.head; + fdc.res[9]=fdc.sector; + fdc.res[10]=fdc.params[4]; + paramstogo=7; +} + +void fdc_no_dma_end() +{ + disctime = 0; + + fdc_int(); + fdc.stat=0xD0; + fdc.res[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; + fdc.res[5]=0x80; /*NDE (No DMA End)*/ + fdc.res[6]=0; + fdc.res[7]=fdc.rw_track; + fdc.res[8]=fdc.head; + fdc.res[9]=fdc.sector; + fdc.res[10]=fdc.params[4]; + paramstogo=7; +} + void fdc_callback() { int temp; @@ -984,18 +1040,7 @@ void fdc_callback() // pclog("Read a track callback, eot=%i\n", fdc.eot[fdc.drive]); if (!fdc.eot[fdc.drive] || fdc.tc) { -// pclog("Complete\n"); - fdc.inread = 0; - discint=-2; - fdc_int(); - fdc.stat=0xD0; - fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; - fdc.res[5]=fdc.res[6]=0; - fdc.res[7]=fdc.rw_track; - fdc.res[8]=fdc.head; - fdc.res[9]=fdc.sector; - fdc.res[10]=fdc.params[4]; - paramstogo=7; + fdc_poll_readwrite_finish(); return; } else @@ -1018,95 +1063,54 @@ void fdc_callback() disctime = 0; return; case 5: /*Write data*/ - readflash = 1; - fdc.sector++; - if (fdc.sector > fdc.params[5]) - { - fdc.sector = 1; - if (fdc.command & 0x80) - { - fdc.head ^= 1; - fdd_set_head(fdc.drive, fdd_get_head(fdc.drive ^ fdd_swap) ^ 1); - if (!fdc.head) - { - fdc.rw_track++; -// fdc.track[fdc.drive]++; -/* if (fdc.track[fdc.drive] >= 79) - { - fdc.track[fdc.drive] = 79; - fdc.tc = 1; - }*/ - } - } - else - { - fdc.rw_track++; -// fdc.track[fdc.drive]++; - fdc.tc = 1; - } - } - if (fdc.tc) - { - discint=-2; - fdc_int(); - fdc.stat=0xD0; - fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; - fdc.res[5]=fdc.res[6]=0; - fdc.res[7]=fdc.rw_track; - fdc.res[8]=fdc.head; - fdc.res[9]=fdc.sector; - fdc.res[10]=fdc.params[4]; - paramstogo=7; - return; - } - disc_writesector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); -// ioc_fiq(IOC_FIQ_DISC_DATA); - return; case 6: /*Read data*/ // rpclog("Read data %i\n", fdc.tc); + if (fdc.tc) + { + fdc_poll_readwrite_finish(); + return; + } readflash = 1; - fdc.sector++; - if (fdc.sector > fdc.params[5]) + if (fdc.sector == fdc.params[5]) { - fdc.sector = 1; - if (fdc.command & 0x80) - { - fdc.head ^= 1; - fdd_set_head(fdc.drive, fdd_get_head(fdc.drive ^ fdd_swap) ^ 1); - if (!fdc.head) - { - fdc.rw_track++; -// fdc.track[fdc.drive]++; -/* if (fdc.track[fdc.drive] >= 79) - { - fdc.track[fdc.drive] = 79; - fdc.tc = 1; - }*/ - } - } - else - { - fdc.rw_track++; -// fdc.track[fdc.drive]++; - fdc.tc = 1; - } + /* Reached end of track, MT bit is clear */ + if (!(fdc.command & 0x80)) + { + fdc.rw_track++; + fdc.sector = 1; + fdc_no_dma_end(); + return; + } + /* Reached end of track, MT bit is set, head is 1 */ + if ((fdc.head & 1)) + { + fdc.rw_track++; + fdc.sector = 1; + fdc.head &= 0xFE; + fdd_set_head(fdc.drive, 0); + fdc_no_dma_end(); + return; + } + if ((fdc.command & 0x80) && (fdd_get_head(fdc.drive ^ fdd_swap) == 0)) + { + fdc.sector = 1; + fdc.head |= 1; + fdd_set_head(fdc.drive, 1); + } } - if (fdc.tc) - { - fdc.inread = 0; - discint=-2; - fdc_int(); - fdc.stat=0xD0; - fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; - fdc.res[5]=fdc.res[6]=0; - fdc.res[7]=fdc.rw_track; - fdc.res[8]=fdc.head; - fdc.res[9]=fdc.sector; - fdc.res[10]=fdc.params[4]; - paramstogo=7; - return; - } - disc_readsector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); + else if (fdc.sector < fdc.params[5]) + { + fdc.sector++; + } + switch (discint) + { + case 5: + disc_writesector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); + break; + case 6: + disc_readsector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]); + break; + } fdc.inread = 1; return; @@ -1275,7 +1279,7 @@ void fdc_callback() void fdc_overrun() { - disc_sector_stop(fdc.drive ^ fdd_swap); + disc_stop(fdc.drive); disctime = 0; fdc_int(); @@ -1528,6 +1532,7 @@ void fdc_add() io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL); fdc.pcjr = 0; fdc.ps1 = 0; + fdc.max_track = 79; } void fdc_add_for_superio() @@ -1544,6 +1549,7 @@ void fdc_add_pcjr() timer_add(fdc_watchdog_poll, &fdc.watchdog_timer, &fdc.watchdog_timer, &fdc); fdc.pcjr = 1; fdc.ps1 = 0; + fdc.max_track = 79; } void fdc_remove() diff --git a/src/fdc.h b/src/fdc.h index 486f02b36..7c479ebd0 100644 --- a/src/fdc.h +++ b/src/fdc.h @@ -19,12 +19,14 @@ int fdc_get_bitcell_period(); /* A few functions to communicate between Super I/O chips and the FDC. */ void fdc_update_is_nsc(int is_nsc); +void fdc_update_max_track(int max_track); void fdc_update_enh_mode(int enh_mode); int fdc_get_rwc(int drive); void fdc_update_rwc(int drive, int rwc); int fdc_get_boot_drive(); void fdc_update_boot_drive(int boot_drive); void fdc_update_densel_polarity(int densel_polarity); +uint8_t fdc_get_densel_polarity(); void fdc_update_densel_force(int densel_force); void fdc_update_drvrate(int drive, int drvrate); void fdc_update_drv2en(int drv2en); diff --git a/src/fdd.c b/src/fdd.c index 56eb9f3b4..2ba5681eb 100644 --- a/src/fdd.c +++ b/src/fdd.c @@ -39,11 +39,6 @@ static struct #define FLAG_HOLE2 32 #define FLAG_DOUBLE_STEP 64 -#define FLAGS_RPM_NONE 0 -#define FLAGS_RPM_300_ONLY 1 -#define FLAGS_RPM_360_ONLY 2 -#define FLAGS_RPM_BOTH 3 - static struct { int max_track; @@ -81,10 +76,6 @@ static struct { /*3.5" ED*/ .max_track = 86, .flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 - }, - { /*3.5" ED 3-Mode*/ - .max_track = 86, - .flags = FLAG_RPM_300| FLAG_RPM_360 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 } }; @@ -92,11 +83,12 @@ int fdd_swap = 0; void fdd_seek(int drive, int track_diff) { - int old_track; - drive ^= fdd_swap; - old_track = fdd[drive].track; + if (!track_diff) + { + return; + } fdd[drive].track += track_diff; @@ -127,36 +119,23 @@ void fdd_set_densel(int densel) fdd[1].densel = densel; } -int fdd_get_flags(int drive) -{ - return drive_types[fdd[drive].type].flags; -} - int fdd_getrpm(int drive) { int hole = disc_hole(drive); - int flags = 0; drive ^= fdd_swap; - flags = fdd_get_flags(drive); - if ((flags & 3) == FLAGS_RPM_300_ONLY) - { - return 300; - } - else if ((flags & 3) == FLAGS_RPM_360_ONLY) - { - return 360; - } + if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_360)) return 300; + if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_300)) return 360; - if (flags & FLAG_525) + if (drive_types[fdd[drive].type].flags & FLAG_525) { return fdd[drive].densel ? 360 : 300; } else { /* disc_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */ - if (hole >= 1) + if (hole == 1) { return fdd[drive].densel ? 300 : 360; } @@ -199,6 +178,11 @@ int fdd_get_type(int drive) return fdd[drive].type; } +int fdd_get_flags(int drive) +{ + return drive_types[fdd[drive].type].flags; +} + int fdd_is_525(int drive) { return drive_types[fdd[drive].type].flags & FLAG_525; diff --git a/src/i440fx.c b/src/i440fx.c index 479b1e313..43889c0ec 100644 --- a/src/i440fx.c +++ b/src/i440fx.c @@ -112,22 +112,25 @@ void i440fx_init() card_i440fx[0x00] = 0x86; card_i440fx[0x01] = 0x80; /*Intel*/ card_i440fx[0x02] = 0x37; card_i440fx[0x03] = 0x12; /*82441FX*/ card_i440fx[0x04] = 0x03; card_i440fx[0x05] = 0x01; - card_i440fx[0x06] = 0x00; card_i440fx[0x07] = 0x00; + card_i440fx[0x06] = 0x80; card_i440fx[0x07] = 0x00; card_i440fx[0x08] = 0x02; /*A0 stepping*/ card_i440fx[0x09] = 0x00; card_i440fx[0x0a] = 0x00; card_i440fx[0x0b] = 0x06; + card_i440fx[0x0d] = 0x00; + card_i440fx[0x0f] = 0x00; card_i440fx[0x2c] = 0xf4; card_i440fx[0x2d] = 0x1a; card_i440fx[0x2e] = 0x00; card_i440fx[0x2f] = 0x11; - // card_i440fx[0x53] = 0x80; - // card_i440fx[0x55] = 0x11; - card_i440fx[0x57] = 0x10; - card_i440fx[0x58] = 0x00; - card_i440fx[0x59] = 0x10; + card_i440fx[0x50] = 0x00; + card_i440fx[0x51] = 0x01; + card_i440fx[0x52] = card_i440fx[0x54] = card_i440fx[0x55] = card_i440fx[0x56] = 0x00; + card_i440fx[0x53] = 0x80; + card_i440fx[0x57] = 0x01; + card_i440fx[0x58] = 0x10; card_i440fx[0x5a] = card_i440fx[0x5b] = card_i440fx[0x5c] = card_i440fx[0x5d] = card_i440fx[0x5e] = 0x11; card_i440fx[0x5f] = 0x31; // card_i440fx[0x60] = card_i440fx[0x61] = card_i440fx[0x62] = card_i440fx[0x63] = card_i440fx[0x64] = card_i440fx[0x65] = card_i440fx[0x66] = card_i440fx[0x67] = 0x02; // card_i440fx[0x70] = 0x20; // card_i440fx[0x71] = 0x10; - card_i440fx[0x72] = 0x0A; + card_i440fx[0x72] = 0x02; } diff --git a/src/ibm.h b/src/ibm.h index 5d91e198f..83671ee3f 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -412,6 +412,9 @@ enum ROM_440FX, /*Unknown / 440FX / Award BIOS / SMC FDC37C665*/ ROM_KN97, /*ASUS KN-97 / 440FX / Award BIOS / Winbond W8387F*/ + + ROM_MARL, /*Intel Advanced/ML / 430HX / AMI BIOS / National Semiconductors PC87306*/ + ROM_THOR, /*Intel Advanced/ATX / 430FX / AMI BIOS / National Semiconductors PC87306*/ ROM_MAX }; diff --git a/src/intel_flash.c b/src/intel_flash.c index 3321652f5..53d81fca3 100644 --- a/src/intel_flash.c +++ b/src/intel_flash.c @@ -6,6 +6,7 @@ #include "device.h" #include "mem.h" +#define FLASH_ALLOW_16 4 #define FLASH_IS_BXB 2 #define FLASH_INVERT 1 @@ -23,7 +24,8 @@ enum CMD_ERASE_SETUP = 0x20, CMD_ERASE_CONFIRM = 0xd0, CMD_ERASE_SUSPEND = 0xb0, - CMD_PROGRAM_SETUP = 0x40 + CMD_PROGRAM_SETUP = 0x40, + CMD_PROGRAM_SETUP2 = 0x10 }; typedef struct flash_t @@ -32,6 +34,7 @@ typedef struct flash_t uint32_t flash_id; uint8_t type; /* 0 = BXT, 1 = BXB */ uint8_t invert_high_pin; /* 0 = no, 1 = yes */ + uint8_t allow_word_write; /* 0 = no, 1 = yes */ mem_mapping_t mapping[8], mapping_h[8]; uint32_t block_start[4], block_end[4], block_len[4]; uint8_t array[131072]; @@ -68,10 +71,35 @@ static uint8_t flash_read(uint32_t addr, void *p) static uint16_t flash_readw(uint32_t addr, void *p) { + // pclog("flash_readw(%08X)\n", addr); flash_t *flash = (flash_t *)p; + if (!flash->allow_word_write) + { + addr &= 0x1ffff; + if (flash->invert_high_pin) addr ^= 0x10000; + return *(uint16_t *)&(flash->array[addr]); + } + if (flash->invert_high_pin) + { + addr ^= 0x10000; + if (addr & 0xfff00000) *(uint16_t *)&(flash->array[addr & 0x1ffff]); + } addr &= 0x1ffff; - if (flash->invert_high_pin) addr ^= 0x10000; - return *(uint16_t *)&(flash->array[addr]); + switch (flash->command) + { + case CMD_READ_ARRAY: + default: + return *(uint16_t *)&(flash->array[addr]); + + case CMD_IID: + // pclog("Flash Read ID 16: %08X\n", addr); + if (addr & 1) + return 0x2274; + return 0x89; + + case CMD_READ_STATUS: + return flash->status; + } } static uint32_t flash_readl(uint32_t addr, void *p) @@ -100,7 +128,7 @@ static void flash_write(uint32_t addr, uint8_t val, void *p) case CMD_ERASE_SETUP: if (val == CMD_ERASE_CONFIRM) { - pclog("flash_write: erase %05x\n", addr); + // pclog("flash_write: erase %05x\n", addr); for (i = 0; i < 3; i++) { @@ -114,7 +142,8 @@ static void flash_write(uint32_t addr, uint8_t val, void *p) break; case CMD_PROGRAM_SETUP: - pclog("flash_write: program %05x %02x\n", addr, val); + case CMD_PROGRAM_SETUP2: + // pclog("flash_write: program %05x %02x\n", addr, val); if ((addr & 0x1e000) != (flash->block_start[3] & 0x1e000)) flash->array[addr] = val; flash->command = CMD_READ_STATUS; @@ -132,14 +161,73 @@ static void flash_write(uint32_t addr, uint8_t val, void *p) } } +static void flash_writew(uint32_t addr, uint16_t val, void *p) +{ + flash_t *flash = (flash_t *)p; + int i; + // pclog("flash_writew : addr=%08x val=%02x command=%02x %04x:%08x\n", addr, val, flash->command, CS, cpu_state.pc); + + if (flash->invert_high_pin) + { + addr ^= 0x10000; + if (addr & 0xfff00000) return; + } + addr &= 0x1ffff; + + switch (flash->command) + { + case CMD_ERASE_SETUP: + if (val == CMD_ERASE_CONFIRM) + { + // pclog("flash_writew: erase %05x\n", addr); + + for (i = 0; i < 3; i++) + { + if ((addr >= flash->block_start[i]) && (addr <= flash->block_end[i])) + memset(&(flash->array[flash->block_start[i]]), 0xff, flash->block_len[i]); + } + + flash->status = 0x80; + } + flash->command = CMD_READ_STATUS; + break; + + case CMD_PROGRAM_SETUP: + case CMD_PROGRAM_SETUP2: + // pclog("flash_writew: program %05x %02x\n", addr, val); + if ((addr & 0x1e000) != (flash->block_start[3] & 0x1e000)) + *(uint16_t *)&(flash->array[addr]) = val; + flash->command = CMD_READ_STATUS; + flash->status = 0x80; + break; + + default: + flash->command = val; + switch (val) + { + case CMD_CLEAR_STATUS: + flash->status = 0; + break; + } + } +} + void intel_flash_add_mappings(flash_t *flash) { int i = 0; for (i = 0; i <= 7; i++) { - mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); - mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), 0, (void *)flash); + if (flash->allow_word_write) + { + mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, flash_writew, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); + mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, flash_writew, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), 0, (void *)flash); + } + else + { + mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); + mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), 0, (void *)flash); + } } } @@ -150,8 +238,16 @@ void intel_flash_add_mappings_inverted(flash_t *flash) for (i = 0; i <= 7; i++) { - mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); - mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), 0, (void *)flash); + if (flash->allow_word_write) + { + mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, flash_writew, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); + mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, flash_writew, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), 0, (void *)flash); + } + else + { + mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); + mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), 0, (void *)flash); + } } } @@ -215,12 +311,19 @@ void *intel_flash_init(uint8_t type) case ROM_KN97: strcpy(flash_path, "roms/kn97/"); break; + case ROM_MARL: + strcpy(flash_path, "roms/marl/"); + break; + case ROM_THOR: + strcpy(flash_path, "roms/thor/"); + break; } // pclog("Flash init: Path is: %s\n", flash_path); flash->type = (type & 2) ? 1 : 0; flash->flash_id = (!flash->type) ? 0x94 : 0x95; flash->invert_high_pin = (type & 1); + flash->allow_word_write = (type & 4) ? 1 : 0; /* The block lengths are the same both flash types. */ flash->block_len[0] = 0x1c000; @@ -321,6 +424,12 @@ void *intel_flash_bxt_ami_init() return intel_flash_init(FLASH_INVERT); } +/* For later AMI BIOS'es - Intel 28F100BXT with high address pin inverted and 16-bit write capability. */ +void *intel_flash_100bxt_ami_init() +{ + return intel_flash_init(FLASH_INVERT | FLASH_ALLOW_16); +} + /* For Award BIOS'es - Intel 28F001BXT with high address pin not inverted. */ void *intel_flash_bxt_init() { @@ -382,6 +491,19 @@ device_t intel_flash_bxt_ami_device = NULL }; +device_t intel_flash_100bxt_ami_device = +{ + "Intel 28F100BXT Flash BIOS", + 0, + intel_flash_100bxt_ami_init, + intel_flash_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; + device_t intel_flash_bxt_device = { "Intel 28F001BXT Flash BIOS", diff --git a/src/intel_flash.h b/src/intel_flash.h index b3d3739d2..ff8fb372b 100644 --- a/src/intel_flash.h +++ b/src/intel_flash.h @@ -2,5 +2,6 @@ see COPYING for more details */ extern device_t intel_flash_bxt_ami_device; +extern device_t intel_flash_100bxt_ami_device; extern device_t intel_flash_bxt_device; extern device_t intel_flash_bxb_device; diff --git a/src/mem.c b/src/mem.c index d1a3d6a51..b1f20d4f0 100644 --- a/src/mem.c +++ b/src/mem.c @@ -727,6 +727,36 @@ int loadbios() fclose(f); biosmask = 0x1ffff; return 1; + + case ROM_MARL: + f = romfopen("roms/marl/1008DB0_.BIO", "rb"); + if (!f) break; + fseek(f, 0x80, SEEK_SET); + fread(rom + 0x10000, 0x10000, 1, f); + fclose(f); + f = romfopen("roms/marl/1008DB0_.BI1", "rb"); + if (!f) break; + fseek(f, 0x80, SEEK_SET); + fread(rom, 0xd000, 1, f); + fclose(f); + biosmask = 0x1ffff; + //is486=1; + return 1; + + case ROM_THOR: + f = romfopen("roms/thor/1005CN0.BIO", "rb"); + if (!f) break; + fseek(f, 0x80, SEEK_SET); + fread(rom + 0x10000, 0x10000, 1, f); + fclose(f); + f = romfopen("roms/thor/1005CN0.BI1", "rb"); + if (!f) break; + fseek(f, 0x80, SEEK_SET); + fread(rom, 0x10000, 1, f); + fclose(f); + biosmask = 0x1ffff; + //is486=1; + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); diff --git a/src/model.c b/src/model.c index ac155ae01..22809a7ae 100644 --- a/src/model.c +++ b/src/model.c @@ -3,8 +3,10 @@ */ #include "ibm.h" #include "cpu.h" +#include "mem.h" #include "model.h" #include "io.h" +#include "rom.h" #include "acer386sx.h" #include "acerm3a.h" @@ -96,9 +98,11 @@ void at_acerm3a_init(); void at_acerv35n_init(); // void at_p55t2p4_init(); void at_p55tvp4_init(); +void at_marl_init(); void at_p55va_init(); void at_i440fx_init(); void at_kn97_init(); +void at_deskpro2k_init(); int model; @@ -152,13 +156,15 @@ MODEL models[] = {"Intel Premiere/PCI II",ROM_PLATO, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, 1, 1, 128, 1, at_plato_init}, {"Intel Advanced/EV", ROM_ENDEAVOR, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, 1, 1, 128, 1, at_endeavor_init}, {"PC Partner MB500N", ROM_MB500N, { "Intel", cpus_PentiumS5,"IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, 1, 1, 128, 1, at_mb500n_init}, + {"Intel Advanced/ATX", ROM_THOR, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_endeavor_init}, // {"ASUS P/I-P54TP4XE", ROM_P54TP4XE, { "Intel", cpus_PentiumS5, "IDT", cpus_WinChip, "AMD", cpus_K5, "", NULL}, 0, 1, 1, 512, 1, at_p54tp4xe_init}, + {"Intel Advanced/ML", ROM_MARL, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_marl_init}, {"Acer M3a", ROM_ACERM3A, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_acerm3a_init}, {"Acer V35N", ROM_ACERV35N, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_acerv35n_init}, - // {"ASUS P/I-P55T2P4", ROM_P55T2P4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_p55t2p4_init}, + // {"ASUS P/I-P55T2P4", ROM_P55T2P4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_p55t2p4_init}, {"Award 430VX PCI", ROM_430VX, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_i430vx_init}, - {"ASUS P/I-P55TVP4", ROM_P55TVP4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 512, 1, at_p55tvp4_init}, {"Epox P55-VA", ROM_P55VA, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_p55va_init}, + {"ASUS P/I-P55TVP4", ROM_P55TVP4, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "Cyrix", cpus_6x86, "AMD", cpus_K56, "", NULL}, 0, 1, 1, 256, 1, at_p55tvp4_init}, {"Award 440FX PCI", ROM_440FX, { "Intel", cpus_PentiumPro, "", NULL, "", NULL}, 0, 1, 1, 1024, 1, at_i440fx_init}, {"Award KN97 (440FX PCI)",ROM_KN97, { "Intel", cpus_PentiumPro, "", NULL, "", NULL}, 0, 1, 1, 1024, 1, at_kn97_init}, // {"Award 440FX PCI", ROM_440FX, { "Intel", cpus_PentiumPro,"Klamath", cpus_Pentium2, "Deschutes", cpus_Pentium2D}, 0, 1, 1, 1024, 1, at_i440fx_init}, @@ -476,7 +482,7 @@ void at_plato_init() if (cdrom_channel >= 4) ide_ter_init(); } -void at_endeavor_init() +void at_advanced_common_init() { at_init(); mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); @@ -485,10 +491,21 @@ void at_endeavor_init() piix_init(7); pc87306_init(); intel_endeavor_init(); - device_add(&intel_flash_bxt_ami_device); if (cdrom_channel >= 4) ide_ter_init(); } +void at_endeavor_init() +{ + at_advanced_common_init(); + device_add(&intel_flash_bxt_ami_device); +} + +void at_marl_init() +{ + at_advanced_common_init(); + device_add(&intel_flash_100bxt_ami_device); +} + void at_mb500n_init() { at_init(); @@ -521,6 +538,7 @@ void at_p54tp4xe_init() void at_acerm3a_init() { at_init(); + memregs_init(); mouse_serial_init(); pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); i430hx_init(); @@ -534,6 +552,7 @@ void at_acerm3a_init() void at_acerv35n_init() { at_init(); + memregs_init(); mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); i430hx_init(); @@ -562,6 +581,7 @@ void at_p55t2p4_init() void at_i430vx_init() { at_init(); + memregs_init(); mouse_serial_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i430vx_init(); @@ -571,6 +591,8 @@ void at_i430vx_init() if (cdrom_channel >= 4) ide_ter_init(); } +// rom_t ami_ec_rom; + void at_p55tvp4_init() { at_init(); @@ -581,12 +603,19 @@ void at_p55tvp4_init() piix3_init(7); w83877f_init(); device_add(&intel_flash_bxt_device); + + /* rom_init(&ami_ec_rom, "roms/AMIINT13.BIN", 0xd0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + pc87306_init(); + + intel_endeavor_init(); */ + if (cdrom_channel >= 4) ide_ter_init(); } void at_p55va_init() { at_init(); + memregs_init(); mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i430vx_init(); @@ -599,7 +628,8 @@ void at_p55va_init() void at_i440fx_init() { at_init(); - mouse_ps2_init(); + memregs_init(); + mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i440fx_init(); piix3_init(7); @@ -612,7 +642,7 @@ void at_kn97_init() { at_init(); memregs_init(); - mouse_ps2_init(); + mouse_always_serial ? mouse_serial_init() : mouse_ps2_init(); pci_init(PCI_CONFIG_TYPE_1, 0, 31); i440fx_init(); piix3_init(7); diff --git a/src/nvr.c b/src/nvr.c index 69d15a3ad..d39dec398 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -241,6 +241,8 @@ void loadnvr() case ROM_P55VA: f = romfopen("nvr/p55va.nvr", "rb"); nvrmask = 127; break; case ROM_440FX: f = romfopen("nvr/440fx.nvr", "rb"); nvrmask = 127; break; case ROM_KN97: f = romfopen("nvr/kn97.nvr", "rb"); nvrmask = 127; break; + case ROM_MARL: f = romfopen("nvr/marl.nvr", "rb"); nvrmask = 127; break; + case ROM_THOR: f = romfopen("nvr/thor.nvr", "rb"); nvrmask = 127; break; default: return; } if (!f) @@ -315,6 +317,8 @@ void savenvr() case ROM_P55VA: f = romfopen("nvr/p55va.nvr", "wb"); break; case ROM_440FX: f = romfopen("nvr/440fx.nvr", "wb"); break; case ROM_KN97: f = romfopen("nvr/kn97.nvr", "wb"); break; + case ROM_MARL: f = romfopen("nvr/marl.nvr", "wb"); break; + case ROM_THOR: f = romfopen("nvr/thor.nvr", "wb"); break; default: return; } fwrite(nvrram,128,1,f); diff --git a/src/pc87306.c b/src/pc87306.c index 475a04d32..c8eb2cc2a 100644 --- a/src/pc87306.c +++ b/src/pc87306.c @@ -178,7 +178,7 @@ process_value: if (val & 2) { serial1_handler(); - // mouse_serial_init(); + if (mouse_always_serial) mouse_serial_init(); } if (val & 4) serial2_handler(); @@ -218,7 +218,7 @@ process_value: if (pc87306_regs[0] & 2) { serial1_handler(); - // mouse_serial_init(); + if (mouse_always_serial) mouse_serial_init(); } if (pc87306_regs[0] & 4) serial2_handler(); break; @@ -237,7 +237,7 @@ process_value: if (pc87306_regs[0] & 2) { serial1_handler(); - // mouse_serial_init(); + if (mouse_always_serial) mouse_serial_init(); } if (pc87306_regs[0] & 4) serial2_handler(); } @@ -293,6 +293,7 @@ void pc87306_init() */ fdc_update_is_nsc(1); fdc_update_densel_polarity(1); + fdc_update_max_track(85); fdd_swap = 0; io_sethandler(0x02e, 0x0002, pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, NULL); } diff --git a/src/piix.c b/src/piix.c index cf58e0d91..ef16f17fe 100644 --- a/src/piix.c +++ b/src/piix.c @@ -546,6 +546,7 @@ void piix3_init(int card) card_piix[0x70] = 0x80; card_piix[0x76] = card_piix[0x77] = 0x0c; card_piix[0x78] = 0x02; card_piix[0x79] = 0x00; + card_piix[0x80] = card_piix[0x82] = 0x00; card_piix[0xa0] = 0x08; card_piix[0xa2] = card_piix[0xa3] = 0x00; card_piix[0xa4] = card_piix[0xa5] = card_piix[0xa6] = card_piix[0xa7] = 0x00; diff --git a/src/w83877f.c b/src/w83877f.c index 968bc74e0..f97168868 100644 --- a/src/w83877f.c +++ b/src/w83877f.c @@ -511,6 +511,7 @@ void w83877f_init() fdc_update_drvrate(0, 0); fdc_update_drvrate(1, 0); fdc_update_enh_mode(0); + fdc_update_max_track(85); swwp = 0; disable_write = 0; fdc_update_drv2en(1); diff --git a/src/win.c b/src/win.c index 30c047467..5f84610fb 100644 --- a/src/win.c +++ b/src/win.c @@ -604,7 +604,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, get_registry_key_map(); ghwnd=hwnd; - + initpc(argc, argv); // pclog("Setting video API...\n"); @@ -614,6 +614,8 @@ int WINAPI WinMain (HINSTANCE hThisInstance, if (vid_resize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW|WS_VISIBLE); else SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)|WS_VISIBLE); + SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_MINIMIZEBOX); + // pclog("Checking CD-ROM menu item...\n"); if (!cdrom_enabled) CheckMenuItem(menu, IDM_CDROM_DISABLED, MF_CHECKED); @@ -1032,6 +1034,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM CheckMenuItem(hmenu, IDM_VID_RESIZE, (vid_resize)?MF_CHECKED:MF_UNCHECKED); if (vid_resize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW|WS_VISIBLE); else SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_THICKFRAME&~WS_MAXIMIZEBOX)|WS_VISIBLE); + SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_MINIMIZEBOX); GetWindowRect(hwnd,&rect); SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); saveconfig(); diff --git a/src/x87_ops.h b/src/x87_ops.h index 1c0db7bdb..637c09968 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -177,17 +177,14 @@ static inline void x87_st_fsave(int reg) static inline void x87_ld_frstor(int reg) { - uint16_t temp; - reg = (cpu_state.TOP + reg) & 7; - temp = readmemw(easeg, cpu_state.eaaddr + 8); + cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr); + cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8); - if (temp == 0x5555 && cpu_state.tag[reg] == 2) + if (cpu_state.MM_w4[reg] == 0x5555 && cpu_state.tag[reg] == 2) { cpu_state.tag[reg] = TAG_UINT64; - cpu_state.MM[reg].q = readmeml(easeg, cpu_state.eaaddr); - cpu_state.MM[reg].q |= ((uint64_t)readmeml(easeg, cpu_state.eaaddr + 4) << 32); cpu_state.ST[reg] = (double)cpu_state.MM[reg].q; } else @@ -290,7 +287,6 @@ typedef union #define FP_ENTER() do \ { \ - flags_rebuild(); \ if (cr0 & 0xc) \ { \ x86_int(7); \ diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index dbd17af19..b7c3c5e34 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -110,14 +110,14 @@ static int FSTOR() cpu_state.eaaddr += 28; break; } - x87_ldmmx(&cpu_state.MM[0], &cpu_state.MM_w4[0]); x87_ld_frstor(0); cpu_state.eaaddr += 10; - x87_ldmmx(&cpu_state.MM[1], &cpu_state.MM_w4[1]); x87_ld_frstor(1); cpu_state.eaaddr += 10; - x87_ldmmx(&cpu_state.MM[2], &cpu_state.MM_w4[2]); x87_ld_frstor(2); cpu_state.eaaddr += 10; - x87_ldmmx(&cpu_state.MM[3], &cpu_state.MM_w4[3]); x87_ld_frstor(3); cpu_state.eaaddr += 10; - x87_ldmmx(&cpu_state.MM[4], &cpu_state.MM_w4[4]); x87_ld_frstor(4); cpu_state.eaaddr += 10; - x87_ldmmx(&cpu_state.MM[5], &cpu_state.MM_w4[5]); x87_ld_frstor(5); cpu_state.eaaddr += 10; - x87_ldmmx(&cpu_state.MM[6], &cpu_state.MM_w4[6]); x87_ld_frstor(6); cpu_state.eaaddr += 10; - x87_ldmmx(&cpu_state.MM[7], &cpu_state.MM_w4[7]); x87_ld_frstor(7); + x87_ld_frstor(0); cpu_state.eaaddr += 10; + x87_ld_frstor(1); cpu_state.eaaddr += 10; + x87_ld_frstor(2); cpu_state.eaaddr += 10; + x87_ld_frstor(3); cpu_state.eaaddr += 10; + x87_ld_frstor(4); cpu_state.eaaddr += 10; + x87_ld_frstor(5); cpu_state.eaaddr += 10; + x87_ld_frstor(6); cpu_state.eaaddr += 10; + x87_ld_frstor(7); cpu_state.ismmx = 0; /*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times