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);
}
|