Merge pull request #2089 from wannacu/main

Implements DAA, DAS, AAA, AAS, AAM and AAD instruction
This commit is contained in:
Ryan Houdek authored and GitHub committed 2022-10-19 03:57:13 -07:00
commit f26eccd00f
9 files changed
+324 -6

No files matched your search

@@ -3342,6 +3342,222 @@ void OpDispatchBuilder::PopcountOp(OpcodeArgs) {
GenerateFlags_POPCOUNT(Op, Src);
}
void OpDispatchBuilder::DAAOp(OpcodeArgs) {
CalculateDeferredFlags();
auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
auto AF = GetRFLAG(FEXCore::X86State::RFLAG_AF_LOC);
auto AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(0));
auto Cond = _Or(AF, _Select(FEXCore::IR::COND_UGT, _And(AL, _Constant(0xF)), _Constant(9), _Constant(1), _Constant(0)));
auto FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock());
auto TrueBlock = CreateNewCodeBlockAfter(FalseBlock);
auto EndBlock = CreateNewCodeBlockAfter(TrueBlock);
_CondJump(Cond, TrueBlock, FalseBlock);
SetCurrentCodeBlock(FalseBlock);
{
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
_Jump(EndBlock);
}
SetCurrentCodeBlock(TrueBlock);
{
auto NewAL = _Add(AL, _Constant(0x6));
_StoreContext(1, GPRClass, NewAL, GPROffset(X86State::REG_RAX));
CalculateDeferredFlags();
auto NewCF = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Or(CF, NewCF));
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(1));
_Jump(EndBlock);
}
SetCurrentCodeBlock(EndBlock);
Cond = _Or(CF, _Select(FEXCore::IR::COND_UGT, AL, _Constant(0x99), _Constant(1), _Constant(0)));
FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock());
TrueBlock = CreateNewCodeBlockAfter(FalseBlock);
EndBlock = CreateNewCodeBlockAfter(TrueBlock);
_CondJump(Cond, TrueBlock, FalseBlock);
SetCurrentCodeBlock(FalseBlock);
{
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(0));
_Jump(EndBlock);
}
SetCurrentCodeBlock(TrueBlock);
{
AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
auto NewAL = _Add(AL, _Constant(0x60));
_StoreContext(1, GPRClass, NewAL, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(1));
_Jump(EndBlock);
}
SetCurrentCodeBlock(EndBlock);
// Update Flags
AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(_Select(FEXCore::IR::COND_UGE, _And(AL, _Constant(0x80)), _Constant(0), _Constant(1), _Constant(0)));
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(_Select(FEXCore::IR::COND_EQ, _And(AL, _Constant(0xFF)), _Constant(0), _Constant(1), _Constant(0)));
auto EightBitMask = _Constant(0xFF);
auto PopCountOp = _Popcount(_And(AL, EightBitMask));
auto XorOp = _Xor(PopCountOp, _Constant(1));
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
}
void OpDispatchBuilder::DASOp(OpcodeArgs) {
CalculateDeferredFlags();
auto CF = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
auto AF = GetRFLAG(FEXCore::X86State::RFLAG_AF_LOC);
auto AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(0));
auto Cond = _Or(AF, _Select(FEXCore::IR::COND_UGT, _And(AL, _Constant(0xf)), _Constant(9), _Constant(1), _Constant(0)));
auto FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock());
auto TrueBlock = CreateNewCodeBlockAfter(FalseBlock);
auto EndBlock = CreateNewCodeBlockAfter(TrueBlock);
_CondJump(Cond, TrueBlock, FalseBlock);
SetCurrentCodeBlock(FalseBlock);
{
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
_Jump(EndBlock);
}
SetCurrentCodeBlock(TrueBlock);
{
auto NewAL = _Sub(AL, _Constant(0x6));
_StoreContext(1, GPRClass, NewAL, GPROffset(X86State::REG_RAX));
CalculateDeferredFlags();
auto NewCF = GetRFLAG(FEXCore::X86State::RFLAG_CF_LOC);
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Or(CF, NewCF));
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(1));
_Jump(EndBlock);
}
SetCurrentCodeBlock(EndBlock);
Cond = _Or(CF, _Select(FEXCore::IR::COND_UGT, AL, _Constant(0x99), _Constant(1), _Constant(0)));
FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock());
TrueBlock = CreateNewCodeBlockAfter(FalseBlock);
EndBlock = CreateNewCodeBlockAfter(TrueBlock);
_CondJump(Cond, TrueBlock, FalseBlock);
SetCurrentCodeBlock(FalseBlock);
{
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(0));
_Jump(EndBlock);
}
SetCurrentCodeBlock(TrueBlock);
{
AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
auto NewAL = _Sub(AL, _Constant(0x60));
_StoreContext(1, GPRClass, NewAL, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(1));
_Jump(EndBlock);
}
SetCurrentCodeBlock(EndBlock);
// Update Flags
AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(_Select(FEXCore::IR::COND_UGE, _And(AL, _Constant(0x80)), _Constant(0), _Constant(1), _Constant(0)));
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(_Select(FEXCore::IR::COND_EQ, _And(AL, _Constant(0xFF)), _Constant(0), _Constant(1), _Constant(0)));
auto EightBitMask = _Constant(0xFF);
auto PopCountOp = _Popcount(_And(AL, EightBitMask));
auto XorOp = _Xor(PopCountOp, _Constant(1));
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
}
void OpDispatchBuilder::AAAOp(OpcodeArgs) {
auto AF = GetRFLAG(FEXCore::X86State::RFLAG_AF_LOC);
auto AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
auto AX = _LoadContext(2, GPRClass, GPROffset(X86State::REG_RAX));
auto Cond = _Or(AF, _Select(FEXCore::IR::COND_UGT, _And(AL, _Constant(0xF)), _Constant(9), _Constant(1), _Constant(0)));
auto FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock());
auto TrueBlock = CreateNewCodeBlockAfter(FalseBlock);
auto EndBlock = CreateNewCodeBlockAfter(TrueBlock);
_CondJump(Cond, TrueBlock, FalseBlock);
SetCurrentCodeBlock(FalseBlock);
{
auto NewAX = _And(AX, _Constant(0xFF0F));
_StoreContext(2, GPRClass, NewAX, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(0));
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
_Jump(EndBlock);
}
SetCurrentCodeBlock(TrueBlock);
{
auto NewAX = _Add(AX, _Constant(0x106));
auto Result = _And(NewAX, _Constant(0xFF0F));
_StoreContext(2, GPRClass, Result, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(1));
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(1));
_Jump(EndBlock);
}
SetCurrentCodeBlock(EndBlock);
}
void OpDispatchBuilder::AASOp(OpcodeArgs) {
auto AF = GetRFLAG(FEXCore::X86State::RFLAG_AF_LOC);
auto AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
auto AX = _LoadContext(2, GPRClass, GPROffset(X86State::REG_RAX));
auto Cond = _Or(AF, _Select(FEXCore::IR::COND_UGT, _And(AL, _Constant(0xF)), _Constant(9), _Constant(1), _Constant(0)));
auto FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock());
auto TrueBlock = CreateNewCodeBlockAfter(FalseBlock);
auto EndBlock = CreateNewCodeBlockAfter(TrueBlock);
_CondJump(Cond, TrueBlock, FalseBlock);
SetCurrentCodeBlock(FalseBlock);
{
auto NewAX = _And(AX, _Constant(0xFF0F));
_StoreContext(2, GPRClass, NewAX, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(0));
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(0));
_Jump(EndBlock);
}
SetCurrentCodeBlock(TrueBlock);
{
auto NewAX = _Sub(AX, _Constant(6));
NewAX = _Sub(NewAX, _Constant(0x100));
auto Result = _And(NewAX, _Constant(0xFF0F));
_StoreContext(2, GPRClass, Result, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_CF_LOC>(_Constant(1));
SetRFLAG<FEXCore::X86State::RFLAG_AF_LOC>(_Constant(1));
_Jump(EndBlock);
}
SetCurrentCodeBlock(EndBlock);
}
void OpDispatchBuilder::AAMOp(OpcodeArgs) {
auto AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
auto Imm8 = _Constant(Op->Src[0].Data.Literal.Value & 0xFF);
auto UDivOp = _UDiv(AL, Imm8);
auto URemOp = _URem(AL, Imm8);
auto AH = _Lshl(UDivOp, _Constant(8));
auto AX = _Add(AH, URemOp);
_StoreContext(2, GPRClass, AX, GPROffset(X86State::REG_RAX));
// Update Flags
AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(_Select(FEXCore::IR::COND_UGE, _And(AL, _Constant(0x80)), _Constant(0), _Constant(1), _Constant(0)));
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(_Select(FEXCore::IR::COND_EQ, _And(AL, _Constant(0xFF)), _Constant(0), _Constant(1), _Constant(0)));
auto EightBitMask = _Constant(0xFF);
auto PopCountOp = _Popcount(_And(AL, EightBitMask));
auto XorOp = _Xor(PopCountOp, _Constant(1));
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
}
void OpDispatchBuilder::AADOp(OpcodeArgs) {
auto AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
auto AH = _Lshr(_LoadContext(2, GPRClass, GPROffset(X86State::REG_RAX)), _Constant(8));
auto Imm8 = _Constant(Op->Src[0].Data.Literal.Value & 0xFF);
auto NewAL = _Add(AL, _Mul(AH, Imm8));
auto Result = _And(NewAL, _Constant(0xFF));
_StoreContext(2, GPRClass, Result, GPROffset(X86State::REG_RAX));
// Update Flags
AL = _LoadContext(1, GPRClass, GPROffset(X86State::REG_RAX));
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(_Select(FEXCore::IR::COND_UGE, _And(AL, _Constant(0x80)), _Constant(0), _Constant(1), _Constant(0)));
SetRFLAG<FEXCore::X86State::RFLAG_ZF_LOC>(_Select(FEXCore::IR::COND_EQ, _And(AL, _Constant(0xFF)), _Constant(0), _Constant(1), _Constant(0)));
auto EightBitMask = _Constant(0xFF);
auto PopCountOp = _Popcount(_And(AL, EightBitMask));
auto XorOp = _Xor(PopCountOp, _Constant(1));
SetRFLAG<FEXCore::X86State::RFLAG_PF_LOC>(XorOp);
}
void OpDispatchBuilder::XLATOp(OpcodeArgs) {
const uint32_t RAXOffset = GPROffset(X86State::REG_RAX);
const uint32_t RBXOffset = GPROffset(X86State::REG_RBX);
@@ -5505,12 +5721,18 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0x17, 1, &OpDispatchBuilder::POPSegmentOp<FEXCore::X86Tables::DecodeFlags::FLAG_SS_PREFIX>},
{0x1E, 1, &OpDispatchBuilder::PUSHSegmentOp<FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX>},
{0x1F, 1, &OpDispatchBuilder::POPSegmentOp<FEXCore::X86Tables::DecodeFlags::FLAG_DS_PREFIX>},
{0x27, 1, &OpDispatchBuilder::DAAOp},
{0x2F, 1, &OpDispatchBuilder::DASOp},
{0x37, 1, &OpDispatchBuilder::AAAOp},
{0x3F, 1, &OpDispatchBuilder::AASOp},
{0x40, 8, &OpDispatchBuilder::INCOp},
{0x48, 8, &OpDispatchBuilder::DECOp},
{0x60, 1, &OpDispatchBuilder::PUSHAOp},
{0x61, 1, &OpDispatchBuilder::POPAOp},
{0xCE, 1, &OpDispatchBuilder::INTOp},
{0xD4, 1, &OpDispatchBuilder::AAMOp},
{0xD5, 1, &OpDispatchBuilder::AADOp},
};
constexpr std::tuple<uint8_t, uint8_t, X86Tables::OpDispatchPtr> BaseOpTable_64[] = {
@@ -278,6 +278,12 @@ public:
void NOTOp(OpcodeArgs);
void XADDOp(OpcodeArgs);
void PopcountOp(OpcodeArgs);
void DAAOp(OpcodeArgs);
void DASOp(OpcodeArgs);
void AAAOp(OpcodeArgs);
void AASOp(OpcodeArgs);
void AAMOp(OpcodeArgs);
void AADOp(OpcodeArgs);
void XLATOp(OpcodeArgs);
template<bool Reseed>
void RDRANDOp(OpcodeArgs);
@@ -266,10 +266,10 @@ void InitializeBaseTables(Context::OperatingMode Mode) {
{0x17, 1, X86InstInfo{"POP SS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_DEF) | FLAGS_DEBUG_MEM_ACCESS, 0, nullptr}},
{0x1E, 1, X86InstInfo{"PUSH DS", TYPE_INST, GenFlagsSrcSize(SIZE_16BIT) | FLAGS_DEBUG_MEM_ACCESS, 0, nullptr}},
{0x1F, 1, X86InstInfo{"POP DS", TYPE_INST, GenFlagsSizes(SIZE_16BIT, SIZE_DEF) | FLAGS_DEBUG_MEM_ACCESS, 0, nullptr}},
{0x27, 1, X86InstInfo{"DAA", TYPE_INST, FLAGS_NONE, 0, nullptr}},
{0x2F, 1, X86InstInfo{"DAS", TYPE_INST, FLAGS_NONE, 0, nullptr}},
{0x37, 1, X86InstInfo{"AAA", TYPE_INST, FLAGS_NONE, 0, nullptr}},
{0x3F, 1, X86InstInfo{"AAS", TYPE_INST, FLAGS_NONE, 0, nullptr}},
{0x27, 1, X86InstInfo{"DAA", TYPE_INST, GenFlagsDstSize(SIZE_8BIT) | FLAGS_SF_DST_RAX, 0, nullptr}},
{0x2F, 1, X86InstInfo{"DAS", TYPE_INST, GenFlagsDstSize(SIZE_8BIT) | FLAGS_SF_DST_RAX, 0, nullptr}},
{0x37, 1, X86InstInfo{"AAA", TYPE_INST, GenFlagsDstSize(SIZE_16BIT) | FLAGS_SF_DST_RAX, 0, nullptr}},
{0x3F, 1, X86InstInfo{"AAS", TYPE_INST, GenFlagsDstSize(SIZE_16BIT) | FLAGS_SF_DST_RAX, 0, nullptr}},
{0x40, 8, X86InstInfo{"INC", TYPE_INST, FLAGS_SF_REX_IN_BYTE, 0, nullptr}},
{0x48, 8, X86InstInfo{"DEC", TYPE_INST, FLAGS_SF_REX_IN_BYTE, 0, nullptr}},
@@ -283,8 +283,8 @@ void InitializeBaseTables(Context::OperatingMode Mode) {
{0xA1, 1, X86InstInfo{"MOV", TYPE_INST, FLAGS_SF_DST_RAX | FLAGS_MEM_OFFSET, 4, nullptr}},
{0xA3, 1, X86InstInfo{"MOV", TYPE_INST, FLAGS_SF_SRC_RAX | FLAGS_MEM_OFFSET, 4, nullptr}},
{0xCE, 1, X86InstInfo{"INTO", TYPE_INST, FLAGS_NONE, 0, nullptr}},
{0xD4, 1, X86InstInfo{"AAM", TYPE_INST, FLAGS_NONE, 1, nullptr}},
{0xD5, 1, X86InstInfo{"AAD", TYPE_INST, FLAGS_NONE, 1, nullptr}},
{0xD4, 1, X86InstInfo{"AAM", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_SF_DST_RAX, 1, nullptr}},
{0xD5, 1, X86InstInfo{"AAD", TYPE_INST, GenFlagsSameSize(SIZE_8BIT) | FLAGS_SF_DST_RAX, 1, nullptr}},
{0xEA, 1, X86InstInfo{"JMPF", TYPE_INST, FLAGS_NONE, 0, nullptr}},
};
@@ -0,0 +1,15 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x12345637"
},
"Mode": "32BIT"
}
%endif
mov eax, 0x1234561f
daa
daa
daa
daa
hlt
@@ -0,0 +1,15 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x12345607"
},
"Mode": "32BIT"
}
%endif
mov eax, 0x1234561f
das
das
das
das
hlt
@@ -0,0 +1,15 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x12345a07"
},
"Mode": "32BIT"
}
%endif
mov eax, 0x1234561f
aaa
aaa
aaa
aaa
hlt
@@ -0,0 +1,15 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x12345107"
},
"Mode": "32BIT"
}
%endif
mov eax, 0x1234561f
aas
aas
aas
aas
hlt
@@ -0,0 +1,15 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0x2"
},
"Mode": "32BIT"
}
%endif
mov eax, 0x1234
aam
aam 0xc
aam 0x1f
aam 0xff
hlt
@@ -0,0 +1,15 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xe8"
},
"Mode": "32BIT"
}
%endif
mov eax, 0x1234
aad
aad 0x3
aad 0x1f
aad 0xae
hlt