Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unittests/ASM: Fixes x87 80-bit loads on the edge of page boundaries. #4169

Merged
merged 3 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4328,6 +4328,14 @@ Ref OpDispatchBuilder::LoadSource_WithOpSize(RegisterClassType Class, const X86T
}

if ((IsOperandMem(Operand, true) && LoadData) || ForceLoad) {
if (OpSize == OpSize::f80Bit) {
Ref MemSrc = LoadEffectiveAddress(A, true);

// For X87 extended doubles, Split the load.
auto Res = _LoadMem(Class, OpSize::i64Bit, MemSrc, Align == OpSize::iInvalid ? OpSize : Align);
return _VLoadVectorElement(OpSize::i128Bit, OpSize::i16Bit, Res, 4, _Add(OpSize::i64Bit, MemSrc, _InlineConstant(8)));
}

return _LoadMemAutoTSO(Class, OpSize, A, Align == OpSize::iInvalid ? OpSize : Align);
} else {
return LoadEffectiveAddress(A, false, AllowUpperGarbage);
Expand Down
4 changes: 2 additions & 2 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void OpDispatchBuilder::SetX87Top(Ref Value) {
void OpDispatchBuilder::FLD(OpcodeArgs, IR::OpSize Width) {
const auto ReadWidth = (Width == OpSize::f80Bit) ? OpSize::i128Bit : Width;

Ref Data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], ReadWidth, Op->Flags);
Ref Data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], Width, Op->Flags);
Ref ConvertedData = Data;
// Convert to 80bit float
if (Width == OpSize::i32Bit || Width == OpSize::i64Bit) {
Expand All @@ -79,7 +79,7 @@ void OpDispatchBuilder::FLDFromStack(OpcodeArgs) {

void OpDispatchBuilder::FBLD(OpcodeArgs) {
// Read from memory
Ref Data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], OpSize::i128Bit, Op->Flags);
Ref Data = LoadSource_WithOpSize(FPRClass, Op, Op->Src[0], OpSize::f80Bit, Op->Flags);
Ref ConvertedData = _F80BCDLoad(Data);
_PushStack(ConvertedData, Data, OpSize::i128Bit, true);
}
Expand Down
32 changes: 32 additions & 0 deletions unittests/ASM/X87/LoadAtBoundary.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
%ifdef CONFIG
{
"RegData": {
"MM7": ["0x5354555657584142", "0x0000000000005152"],
"MM6": ["0xe94de5eae34fc1c0", "0x0000000000004039"]
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif

finit ; enters x87 state

mov rax, 0x100000000
mov rbx, 0x4142434445464748
mov rcx, 0x5152535455565758
mov rdx, (0x100000000 + 0x1000 - 16)

mov [rdx], rbx
mov [rdx + 8], rcx

mov rdx, 0x100000000 + 0x1000

; Do an 80-bit load at the edge of a page.
; Ensuring tword loads don't extend past the end of a page.
fld tword [rdx - 10]

; Do an 80-bit BCD load at the edge of a page.
fbld [rdx - 10]

hlt
33 changes: 33 additions & 0 deletions unittests/ASM/X87/StoreAtBoundary.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif

finit ; enters x87 state

mov rax, 0x100000000
mov rbx, 0x4142434445464748
mov rcx, 0x5152535455565758
mov rdx, (0x100000000 + 0x1000 - 16)

mov [rdx], rbx
mov [rdx + 8], rcx

mov rdx, 0x100000000 + 0x1000

; Load the data in to an x87 register for storing.
fld tword [rdx - 16]
fld tword [rdx - 16]

; Do an 80-bit store at the edge of a page.
; Ensuring tword stores don't extend past the end of a page.
; If storing past the end of the page, then an unhandled SIGSEGV will occur.
fstp tword [rdx - 10]

; Do an 80-bit bcd store at the edge of a page.
fbstp [rdx - 10]

hlt
12 changes: 8 additions & 4 deletions unittests/InstructionCountCI/FlagM/x87.json
Original file line number Diff line number Diff line change
Expand Up @@ -6869,12 +6869,14 @@
]
},
"fld tword [rax]": {
"ExpectedInstructionCount": 12,
"ExpectedInstructionCount": 14,
"Comment": [
"0xdb !11b /5"
],
"ExpectedArm64ASM": [
"ldr q2, [x4]",
"ldr d2, [x4]",
"add x20, x4, #0x8 (8)",
"ld1 {v2.h}[4], [x20]",
"ldrb w20, [x28, #1019]",
"mov w21, #0x1",
"sub w20, w20, #0x1 (1)",
Expand Down Expand Up @@ -16690,12 +16692,14 @@
]
},
"fbld tword [rax]": {
"ExpectedInstructionCount": 40,
"ExpectedInstructionCount": 42,
"Comment": [
"0xdf !11b /4"
],
"ExpectedArm64ASM": [
"ldr q2, [x4]",
"ldr d2, [x4]",
"add x20, x4, #0x8 (8)",
"ld1 {v2.h}[4], [x20]",
"mrs x0, nzcv",
"str w0, [x28, #1000]",
"stp x4, x7, [x28, #280]",
Expand Down
12 changes: 8 additions & 4 deletions unittests/InstructionCountCI/x87.json
Original file line number Diff line number Diff line change
Expand Up @@ -6868,12 +6868,14 @@
]
},
"fld tword [rax]": {
"ExpectedInstructionCount": 12,
"ExpectedInstructionCount": 14,
"Comment": [
"0xdb !11b /5"
],
"ExpectedArm64ASM": [
"ldr q2, [x4]",
"ldr d2, [x4]",
"add x20, x4, #0x8 (8)",
"ld1 {v2.h}[4], [x20]",
"ldrb w20, [x28, #1019]",
"mov w21, #0x1",
"sub w20, w20, #0x1 (1)",
Expand Down Expand Up @@ -16532,12 +16534,14 @@
]
},
"fbld tword [rax]": {
"ExpectedInstructionCount": 40,
"ExpectedInstructionCount": 42,
"Comment": [
"0xdf !11b /4"
],
"ExpectedArm64ASM": [
"ldr q2, [x4]",
"ldr d2, [x4]",
"add x20, x4, #0x8 (8)",
"ld1 {v2.h}[4], [x20]",
"mrs x0, nzcv",
"str w0, [x28, #1000]",
"stp x4, x7, [x28, #280]",
Expand Down
Loading