diff options
-rw-r--r-- | 010vm.cc | 6 | ||||
-rw-r--r-- | 023float.cc | 48 | ||||
-rw-r--r-- | 033check_operands.cc | 1 |
3 files changed, 55 insertions, 0 deletions
diff --git a/010vm.cc b/010vm.cc index 7aca164b..f2ea4c9d 100644 --- a/010vm.cc +++ b/010vm.cc @@ -185,6 +185,9 @@ inline uint32_t read_mem_u32(uint32_t addr) { inline int32_t read_mem_i32(uint32_t addr) { return static_cast<int32_t>(read_mem_u32(addr)); } +inline float read_mem_f32(uint32_t addr) { + return static_cast<float>(read_mem_u32(addr)); +} inline uint8_t* mem_addr_u8(uint32_t addr) { uint8_t* result = NULL; @@ -224,6 +227,9 @@ inline uint32_t* mem_addr_u32(uint32_t addr) { inline int32_t* mem_addr_i32(uint32_t addr) { return reinterpret_cast<int32_t*>(mem_addr_u32(addr)); } +inline float* mem_addr_f32(uint32_t addr) { + return reinterpret_cast<float*>(mem_addr_u32(addr)); +} // helper for some syscalls. But read-only. inline const char* mem_addr_kernel_string(uint32_t addr) { return reinterpret_cast<const char*>(mem_addr_u8(addr)); diff --git a/023float.cc b/023float.cc index e87368cc..fbf7ee40 100644 --- a/023float.cc +++ b/023float.cc @@ -29,3 +29,51 @@ case 0x2a: { // convert integer to float trace(Callstack_depth+1, "run") << Xname[dest] << " is now " << Xmm[dest] << end(); break; } + +//:: divide + +:(before "End Initialize Op Names") +put_new(Name_f3_0f, "5e", "divide floats (divss)"); + +:(code) +void test_divss() { + Xmm[0] = 3.0; + Xmm[1] = 2.0; + run( + "== code 0x1\n" + // op ModR/M SIB displacement immediate + "f3 0f 5e c1 \n" + // ModR/M in binary: 11 (direct mode) 000 (XMM0) 001 (XMM1) + ); + CHECK_TRACE_CONTENTS( + "run: divide x32 by x/m32\n" + "run: x/m32 is XMM1\n" + "run: XMM0 is now 1.5\n" + ); +} + +:(before "End Three-Byte Opcodes Starting With f3 0f") +case 0x5e: { // divide x32 by x/m32 + const uint8_t modrm = next(); + const uint8_t dest = (modrm>>3)&0x7; + trace(Callstack_depth+1, "run") << "divide x32 by x/m32" << end(); + const float* src = effective_address_float(modrm); + Xmm[dest] /= *src; + trace(Callstack_depth+1, "run") << Xname[dest] << " is now " << Xmm[dest] << end(); + break; +} + +:(code) +float* effective_address_float(uint8_t modrm) { + const uint8_t mod = (modrm>>6); + // ignore middle 3 'reg opcode' bits + const uint8_t rm = modrm & 0x7; + if (mod == 3) { + // mod 3 is just register direct addressing + trace(Callstack_depth+1, "run") << "x/m32 is " << Xname[rm] << end(); + return &Xmm[rm]; + } + uint32_t addr = effective_address_number(modrm); + trace(Callstack_depth+1, "run") << "effective address contains " << read_mem_f32(addr) << end(); + return mem_addr_f32(addr); +} diff --git a/033check_operands.cc b/033check_operands.cc index 3e1f12d1..7d73c97f 100644 --- a/033check_operands.cc +++ b/033check_operands.cc @@ -689,6 +689,7 @@ map</*op*/string, /*bitvector*/uint8_t> Permitted_operands_f3_0f; // imm32 imm8 disp32 |disp16 disp8 subop modrm // 0 0 0 |0 0 0 1 put_new(Permitted_operands_f3_0f, "2a", 0x01); +put_new(Permitted_operands_f3_0f, "5e", 0x01); :(code) void check_operands_0f(const line& inst, const word& op) { |