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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
#include "stdafx.h"
#include "Code/Binary.h"
#include "Code/Listing.h"
using namespace code;
BEGIN_TEST(FloatTest, Code) {
Engine &e = gEngine();
Arena *arena = code::arena(e);
Listing *l = new (e) Listing();
Var p1 = l->createFloatParam();
Var p2 = l->createFloatParam();
Var v1 = l->createIntVar(l->root());
*l << prolog();
*l << mov(eax, p1);
*l << fmul(eax, p2);
*l << mov(v1, intConst(10));
*l << icastf(ebx, v1);
*l << fmul(Operand(eax), ebx);
*l << fcasti(eax, eax);
l->result = intDesc(e);
*l << fnRet(eax);
Binary *b = new (e) Binary(arena, l);
typedef Int (*Fn)(Float, Float);
Fn fn = (Fn)b->address();
// Note: the result is 270.6 truncated to 270.
CHECK_EQ((*fn)(12.3f, 2.2f), 270);
} END_TEST
BEGIN_TEST(FloatConstTest, Code) {
Engine &e = gEngine();
Arena *arena = code::arena(e);
Listing *l = new (e) Listing();
*l << prolog();
*l << mov(eax, floatConst(10.2f));
l->result = floatDesc(e);
*l << fnRet(eax);
Binary *b = new (e) Binary(arena, l);
typedef Float (*Fn)();
Fn fn = (Fn)b->address();
CHECK_EQ((*fn)(), 10.2f);
} END_TEST
BEGIN_TEST(FloatFromNatTest, Code) {
Engine &e = gEngine();
Arena *arena = code::arena(e);
Listing *l = new (e) Listing(false, floatDesc(e));
Var param = l->createParam(intDesc(e));
*l << prolog();
*l << ucastf(eax, param);
*l << fnRet(eax);
Binary *b = new (e) Binary(arena, l);
typedef Float (*Fn)(Nat);
Fn fn = (Fn)b->address();
// Too large for a signed int:
CHECK_EQ((*fn)(3000000000), 3000000000.0f);
} END_TEST
BEGIN_TEST(FloatFromWordTest, Code) {
Engine &e = gEngine();
Arena *arena = code::arena(e);
Listing *l = new (e) Listing(false, floatDesc(e));
Var param = l->createParam(longDesc(e));
*l << prolog();
*l << ucastf(eax, param);
*l << fnRet(eax);
Binary *b = new (e) Binary(arena, l);
typedef Float (*Fn)(Word);
Fn fn = (Fn)b->address();
// Too large for a signed long:
CHECK_EQ((*fn)(100000), 100000); // Separate code-path on x86.
CHECK_EQ((*fn)(10000000000000000000u), 10000000000000000000.0f);
} END_TEST
BEGIN_TEST(FloatToNatTest, Code) {
Engine &e = gEngine();
Arena *arena = code::arena(e);
Listing *l = new (e) Listing(false, intDesc(e));
Var param = l->createParam(floatDesc(e));
*l << prolog();
*l << fcastu(eax, param);
*l << fnRet(eax);
Binary *b = new (e) Binary(arena, l);
typedef Nat (*Fn)(Float);
Fn fn = (Fn)b->address();
// Too large for a signed int. Number is small enough to be stored accurately in a float it seems.
CHECK_EQ((*fn)(3000000000.0f), Nat(3000000000));
} END_TEST
BEGIN_TEST(FloatToWordTest, Code) {
Engine &e = gEngine();
Arena *arena = code::arena(e);
Listing *l = new (e) Listing(false, longDesc(e));
Var param = l->createParam(floatDesc(e));
*l << prolog();
*l << fcastu(rax, param);
*l << fnRet(rax);
Binary *b = new (e) Binary(arena, l);
typedef Word (*Fn)(Float);
Fn fn = (Fn)b->address();
// Too large for a signed long. Floats are inexact, so we make sure that the sign is handled properly.
CHECK_GT((*fn)(10000000000000000000.0f), Word(9500000000000000000u));
CHECK_EQ((*fn)(133.0f), Word(133));
CHECK_EQ((*fn)(-133.0f), Word(0)); // This is how the X86 implementation works, others may differ.
} END_TEST
|