Skip to content

Commit

Permalink
Added a workaround for a very rare situation in which the compiler ig…
Browse files Browse the repository at this point in the history
…nores SetFLAGSorEFLAGS in IRET. I am 93% sure it is a bug of clang on Linux. But, there always is a possibility that I am overlooking something.
  • Loading branch information
captainys committed Jun 3, 2024
1 parent 03aa024 commit 7f2326c
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/cpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ i486fidelity.h
i486runinstruction.h
i486templatefunctions.h
i486debugVxD.cpp
i486garbage.cpp
)
target_link_libraries(cpu device ramrom inout cpputil)
target_include_directories(cpu PUBLIC .)
2 changes: 2 additions & 0 deletions src/cpu/i486.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ Therefore, the CPU class now is divided into three parts. The base class, i486C

class i486DXCommon : public CPU
{
public:
void ConsumeVariable(uint32_t); // See comments.
public:
enum
{
Expand Down
4 changes: 4 additions & 0 deletions src/cpu/i486garbage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "i486.h"
void i486DXCommon::ConsumeVariable(unsigned int variable)
{
}
15 changes: 15 additions & 0 deletions src/cpu/i486runinstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -7407,6 +7407,18 @@ unsigned int i486DXFidelityLayer<FIDELITY>::RunOneInstruction(Memory &mem,InOut
SetFLAGSorEFLAGS(inst.operandSize,eflags);
FIDELITY::RestoreIOPLBits(*this,ioplBits);
FIDELITY::RestoreIF(*this,ioplBits);

// If I print state.EFLAGS here, it is updated correctly.
// If I do not print state.EFLAGS, it is not updated from time to time.
// Looks like I stepped on a bug of clang. I need to be careful to declare it as a clang bug,
// but it happens only in Linux using clang 6.0.0-1ubuntu2.
// It does not seem to happen with my clang on macOS.
// I need to let state.EFLAGS consumed by outside of this function, outside of this object file,
// to make it run correctly. Otherwise, the compiler seems to ignore above SetFLAGSorEFLAGS.
#ifdef __linux__
ConsumeVariable(state.EFLAGS);
#endif

state.EFLAGS&=EFLAGS_MASK;
state.EFLAGS|=EFLAGS_ALWAYS_ON;

Expand Down Expand Up @@ -7446,6 +7458,9 @@ unsigned int i486DXFidelityLayer<FIDELITY>::RunOneInstruction(Memory &mem,InOut
typename FIDELITY::EFLAGS ioplBits;
FIDELITY::SaveEFLAGS(ioplBits,*this);
SetFLAGSorEFLAGS(inst.operandSize,eflags);
#ifdef __linux__
ConsumeVariable(state.EFLAGS);
#endif
FIDELITY::RestoreIOPLBits(*this,ioplBits);
FIDELITY::RestoreIF(*this,ioplBits);

Expand Down

0 comments on commit 7f2326c

Please sign in to comment.