about summary refs log tree commit diff stats
path: root/023float.cc
blob: fbf7ee40514c667bd8a2a968f0835a51f334193f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//: floating-point operations

:(before "End Initialize Op Names")
put_new(Name_f3_0f, "2a", "convert integer to floating-point (cvtsi2ss)");

:(code)
void test_cvtsi2ss() {
  Reg[EAX].i = 10;
  run(
      "== code 0x1\n"
      // op     ModR/M  SIB   displacement  immediate
      "f3 0f 2a c0                                    \n"
      // ModR/M in binary: 11 (direct mode) 000 (XMM0) 000 (EAX)
  );
  CHECK_TRACE_CONTENTS(
      "run: convert r/m32 to XMM0\n"
      "run: r/m32 is EAX\n"
      "run: XMM0 is now 10\n"
  );
}

:(before "End Three-Byte Opcodes Starting With f3 0f")
case 0x2a: {  // convert integer to float
  const uint8_t modrm = next();
  const uint8_t dest = (modrm>>3)&0x7;
  trace(Callstack_depth+1, "run") << "convert r/m32 to " << Xname[dest] << end();
  const int32_t* src = effective_address(modrm);
  Xmm[dest] = *src;
  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);
}