1 //===-- tests/test_allinstructions.cpp --------------------------*- C++ -*-===//
2 // Test all instruction encodings provided by JITCS.
4 // Copyright (C) 2013-2014 Dirk Steinke.
5 // See copyright and license notice in COPYRIGHT or include/jitcs.h
7 // Will report wrong encodings, and instructions which have not been encoded
8 // at all. For that purpose, we pull in several *.as files from the _bin/{arch}
9 // directory. These *.as files have been created from *.ins files in
10 // tests/{arch}, enriched by the target encodings as used by NASM.
11 //===----------------------------------------------------------------------===//
15 #include "jitcs_instructionstream.h"
16 #include "jitcs_dumper.h"
17 #include "jitcs_memmgr.h"
18 #include "jitcs_x86_32.h"
19 #include "jitcs_x86_64.h"
20 #include <unordered_set>
21 #include "jitcs_int_machine.h"
22 #include "jitcs_int_bitfuncs.h"
23 #include "test_asm_x86_32.h"
24 #include "test_asm_x86_64.h"
28 using namespace jitcs
;
30 static void test(UnitTest
& t
) {
31 typedef void (__cdecl
*FT0_c
)();
32 RefCounter
<TempAllocator
> alloc(new TempAllocator
);
33 RefCounter
<MemoryMgr
> mgr
= MemoryMgr::Create();
36 std::string path
= "data\\";
38 std::string path
= "data/";
41 std::vector
<std::string
> x86as_files
;
42 x86as_files
.push_back("mov_set");
43 x86as_files
.push_back("arith");
44 x86as_files
.push_back("other");
45 x86as_files
.push_back("other_vex");
46 x86as_files
.push_back("simd_mov");
47 x86as_files
.push_back("simd_arith");
48 x86as_files
.push_back("simd_blend");
49 x86as_files
.push_back("simd_cvt");
50 x86as_files
.push_back("simd_insext");
51 x86as_files
.push_back("simd_shuffle");
52 x86as_files
.push_back("simd_mov_vex");
53 x86as_files
.push_back("simd_arith_vex");
54 x86as_files
.push_back("simd_blend_vex");
55 x86as_files
.push_back("simd_cvt_vex");
56 x86as_files
.push_back("simd_insext_vex");
57 x86as_files
.push_back("simd_shuffle_vex");
58 x86as_files
.push_back("cf");
59 x86as_files
.push_back("addrmode");
61 std::unordered_set
<u32
> allins
;
62 std::unordered_set
<u32
> allins_compressed
;
64 std::string prefix
= path
+ "x86_32_";
66 RefCounter
<IMachineInfo
> mi
= GetX86_32WinMachineInfo();
67 TestAssemblerX86_32
asm_win32(mgr
, alloc
, mi
);
69 allins_compressed
.clear();
71 for (auto fn
: x86as_files
)
72 asm_win32
.checkFile(t
, prefix
+ fn
+ ".as", &allins
,
73 prefix
+ fn
+ ".bin");
75 for (auto v
: allins
) {
76 u32 vv
= v
& 0x7fffffff;
77 allins_compressed
.insert(((vv
>> x86_32::ICL_NonMainBits
) << x86_32::ICL_SubBits
)
78 + (vv
& x86_32::ICL_SubMask
));
82 for (u32 i
= x86_32::ICL_First
; i
< x86_32::ICL_Last
; ++i
) {
83 n
+= popcnt(x86_32::ToValidMask(static_cast<x86_32::InsClassId
>(i
)));
86 sprintf(buffer
, "x86_32/completeness: %d ins available, %d ins handled", n
, allins_compressed
.size());
87 t
.check(buffer
, n
== allins_compressed
.size());
88 if (n
> allins_compressed
.size()) {
90 MachineDumper
md(dd
, *mi
);
91 md
.write("unhandled:");
92 for (u32 i
= x86_32::ICL_First
; i
< x86_32::ICL_Last
; ++i
) {
93 u32 mask
= x86_32::ToValidMask(static_cast<x86_32::InsClassId
>(i
));
94 for (size_t i2
= 0; i2
< 32; ++i2
) {
95 if ((mask
& (1 << i2
)) == 0) continue;
96 u32 a
= (i
<< x86_32::ICL_NonMainBits
) + i2
;
97 u32 b
= (i
<< x86_32::ICL_SubBits
) + i2
;
98 if (allins_compressed
.find(b
) == allins_compressed
.end()) {
100 md
.write(static_cast<InsId
>(a
));
109 std::string prefix
= path
+ "x86_64_";
111 RefCounter
<IMachineInfo
> mi
= GetX86_64WinMachineInfo();
112 TestAssemblerX86_64
asm_win64(mgr
, alloc
, mi
);
114 allins_compressed
.clear();
116 for (auto fn
: x86as_files
)
117 asm_win64
.checkFile(t
, prefix
+ fn
+ ".as", &allins
,
118 prefix
+ fn
+ ".bin");
120 for (auto v
: allins
) {
121 u32 vv
= v
& 0x7fffffff;
122 allins_compressed
.insert
123 (((vv
>> x86_64::ICL_NonMainBits
) << x86_64::ICL_SubBits
)
124 + (vv
& x86_64::ICL_SubMask
));
128 for (u32 i
= x86_64::ICL_First
; i
< x86_64::ICL_Last
; ++i
) {
129 n
+= popcnt(x86_64::ToValidMask(static_cast<x86_64::InsClassId
>(i
)));
132 sprintf(buffer
, "x86_64/completeness: %d ins available, %d ins handled", n
, allins_compressed
.size());
133 t
.check(buffer
, n
== allins_compressed
.size());
134 if (n
> allins_compressed
.size()) {
136 MachineDumper
md(dd
, *mi
);
137 md
.write("unhandled:");
138 for (u32 i
= x86_64::ICL_First
; i
< x86_64::ICL_Last
; ++i
) {
139 u32 mask
= x86_64::ToValidMask(static_cast<x86_64::InsClassId
>(i
));
140 for (size_t i2
= 0; i2
< 32; ++i2
) {
141 if ((mask
& (1 << i2
)) == 0) continue;
142 u32 a
= (i
<< x86_64::ICL_NonMainBits
) + i2
;
143 u32 b
= (i
<< x86_64::ICL_SubBits
) + i2
;
144 if (allins_compressed
.find(b
) == allins_compressed
.end()) {
146 md
.write(static_cast<InsId
>(a
));
156 static UnitTestRun
_("AllInstructions", test
);