summaryrefslogtreecommitdiff
path: root/DevTools
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-07-11 15:52:53 +0200
committerAndreas Kling <kling@serenityos.org>2020-07-11 15:52:53 +0200
commit9db588daf19a5b5fb64b0ad5745d1961ae03448e (patch)
tree3e55c9ac99351c5d2f8442212a647290b3bf6460 /DevTools
parent7d41b95071a3e445b36c72fc6f2662e70bfe110e (diff)
downloadserenity-9db588daf19a5b5fb64b0ad5745d1961ae03448e.zip
UserspaceEmulator: Convert the SUB instruction to inline assembly
Diffstat (limited to 'DevTools')
-rw-r--r--DevTools/UserspaceEmulator/SoftCPU.cpp30
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;
}