diff options
author | Andreas Kling <kling@serenityos.org> | 2020-07-11 15:52:53 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-11 15:52:53 +0200 |
commit | 9db588daf19a5b5fb64b0ad5745d1961ae03448e (patch) | |
tree | 3e55c9ac99351c5d2f8442212a647290b3bf6460 /DevTools | |
parent | 7d41b95071a3e445b36c72fc6f2662e70bfe110e (diff) | |
download | serenity-9db588daf19a5b5fb64b0ad5745d1961ae03448e.zip |
UserspaceEmulator: Convert the SUB instruction to inline assembly
Diffstat (limited to 'DevTools')
-rw-r--r-- | DevTools/UserspaceEmulator/SoftCPU.cpp | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index ea2ee7461c..61f0b11e69 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -151,11 +151,31 @@ static typename TypeDoubler<Destination>::type op_xor(SoftCPU& cpu, const Destin template<typename Destination, typename Source> static typename TypeDoubler<Destination>::type op_sub(SoftCPU& cpu, const Destination& dest, const Source& src) { - u64 result = (u64)dest - (u64)src; - cpu.set_zf(result == 0); - cpu.set_sf((result >> (X86::TypeTrivia<Destination>::bits - 1) & 1)); - cpu.set_af((((result ^ (src ^ dest)) & 0x10) >> 4) & 1); - cpu.set_of((((result ^ dest) & (src ^ dest)) >> (X86::TypeTrivia<Destination>::bits - 1)) & 1); + Destination result = 0; + u32 new_flags = 0; + + if constexpr (sizeof(Destination) == 4) { + asm volatile("subl %%ecx, %%eax\n" + : "=a"(result) + : "a"(dest), "c"(src)); + } else if constexpr (sizeof(Destination) == 2) { + asm volatile("subw %%cx, %%ax\n" + : "=a"(result) + : "a"(dest), "c"(src)); + } else if constexpr (sizeof(Destination) == 1) { + asm volatile("subb %%cl, %%al\n" + : "=a"(result) + : "a"(dest), "c"(src)); + } else { + ASSERT_NOT_REACHED(); + } + + asm volatile( + "pushf\n" + "pop %%ebx" + : "=b"(new_flags)); + + cpu.set_flags_oszap(new_flags); return result; } |