1 #/bin/emblua LUAPREFIX=/*|
7 /*| function pred_ipairs(t, pred)
8 /*| return function(t,k)
13 /*| until not v or pred(k, v)
17 /*| function isa(v) return not v[N==32 and "x64" or "x32only"] end
18 /*| function isaN(k,v) return not v[N==32 and "x64" or "x32"] end
19 #include "test_asm_x86_%(N).h"
20 #include "jitcs_machine.h"
21 #include "jitcs_tmpalloc.h"
22 #include "jitcs_memmgr.h"
23 #include "jitcs_function.h"
24 #include "jitcs_int_virtualregister.h"
28 using namespace jitcs;
30 TestAssemblerX86_%(N)::TestAssemblerX86_%(N)
31 (RefCounter<MemoryMgr> m,
32 RefCounter<TempAllocator> a,
33 RefCounter<IMachineInfo> mi)
34 : TestAssembler(m, a, mi) {
35 assert(mi->cpu.isX86_%(N)());
38 template <typename T> static T* unconst(const T* p) {
39 return const_cast<T*>(p);
41 bool TestAssemblerX86_%(N)::makeGR8Ref
42 (RefOrNull<const VirtualRegister>& r, std::string const& n) {
43 const VirtualRegister* v = findReg(n);
44 if (!v || !x86_%(N)::IsGR8(v->regclass)) return false;
48 bool TestAssemblerX86_%(N)::makeGR16Ref
49 (RefOrNull<const VirtualRegister>& r, std::string const& n) {
50 const VirtualRegister* v = findReg(n);
51 if (!v || !x86_%(N)::IsGR16(v->regclass)) return false;
55 bool TestAssemblerX86_%(N)::makeGR32Ref
56 (RefOrNull<const VirtualRegister>& r, std::string const& n) {
57 const VirtualRegister* v = findReg(n);
58 if (!v || !x86_%(N)::IsGR32(v->regclass)) return false;
63 bool TestAssemblerX86_%(N)::makeGR64Ref
64 (RefOrNull<const VirtualRegister>& r, std::string const& n) {
65 const VirtualRegister* v = findReg(n);
66 if (!v || !x86_%(N)::IsGR64(v->regclass)) return false;
71 bool TestAssemblerX86_%(N)::makeGRRef
72 (RefOrNull<const VirtualRegister>& r, std::string const& n) {
73 return makeGR%(N)Ref(r, n);
75 bool TestAssemblerX86_%(N)::makeVR128Ref
76 (RefOrNull<const VirtualRegister>& r, std::string const& n) {
77 const VirtualRegister* v = findReg(n);
78 if (!v || !x86_%(N)::IsVR128(v->regclass)) return false;
82 bool TestAssemblerX86_%(N)::makeVR256Ref
83 (RefOrNull<const VirtualRegister>& r, std::string const& n) {
84 const VirtualRegister* v = findReg(n);
85 if (!v || !x86_%(N)::IsVR256(v->regclass)) return false;
89 bool TestAssemblerX86_%(N)::makeBBRef
90 (RefOrNull<BasicBlock>& bb, std::string const& n) {
91 std::string n2 = toLower(n);
92 if (bbnames.find(n2) != bbnames.end()) {
96 Ref<BasicBlock> newbb = fnc->createBasicBlock();
97 bbnames[n2] = newbb._ptr;
101 bool TestAssemblerX86_%(N)::makei64(i64& v, std::string const& n) {
104 if (n.size() >= 3 && n[0] == '0' && (n[1] | 0x20) == 'x') {
105 x = strtoll(n.c_str() + 2, &e, 16);
107 x = strtoll(n.c_str(), &e, 10);
108 if (e && *e) return false;
109 if (errno == ERANGE) return false;
113 bool TestAssemblerX86_%(N)::makei8(i8& v, std::string const& n) {
115 if (!makei64(x, n)) return false;
116 if (x < -128 || x > 256-1) return false;
120 bool TestAssemblerX86_%(N)::makei16(i16& v, std::string const& n) {
122 if (!makei64(x, n)) return false;
123 if (x < -128*256 || x > 256*256-1) return false;
127 bool TestAssemblerX86_%(N)::makei32(i32& v, std::string const& n) {
129 if (!makei64(x, n)) return false;
130 if (x < -128*256*256*256 || x > 0xffffffff) return false;
134 bool TestAssemblerX86_%(N)::makeMemRef
135 (RefOrNull<MemoryReference>& m, std::string const& n) {
136 if (n.substr(0,1) != "[" || n.substr(n.size()-1) != "]") return false;
137 std::vector<std::string> summands;
138 split(n.substr(1,n.size()-2), "+", summands);
139 if (summands.size() > 0) {
141 split(summands[summands.size()-1], "-", p1, p2);
142 if (p1.size() > 0 && p2.size() > 0) {
143 summands.erase(summands.begin() + summands.size() - 1);
144 summands.push_back(p1);
145 summands.push_back("-" + p2);
149 if (summands.size() < 1 || summands.size() > 3) return false;
152 std::string first = toLower(summands[0]);
154 if (summands.size() != 2) return false;
156 if (!makei32(x, summands[1])) return false;
157 Ref<MemoryReference> ptr = memstream->alloc();
158 ptr->setSPRelative(x);
162 if (first.substr(0,2) == "fp") {
163 int fpno = atoi(first.c_str() + 2);
164 if (fpno < 1 || fpno > 7) return false;
165 if (summands.size() != 2) return false;
167 if (!makei32(x, summands[1])) return false;
168 Ref<MemoryReference> ptr = memstream->alloc();
169 ptr->setFPRelative(fpno, x);
173 // gpr [+ gpr * s] [+ o]
174 RefOrNull<const VirtualRegister> base = nullptr, index = nullptr;
175 i32 offset = 0, scale = 1;
176 if (!makeGRRef(base, summands[0])) return false;
179 if (summands.size() >= 2) {
180 split(summands[1], "*", q1, q2);
181 if (q1.size() > 0 && q2.size() > 0) {
182 if (makeGRRef(index, q1) && makei32(scale, q2)) {
183 if (scale < 1 || scale > 8 || ((1 << scale) & (0x116)) == 0) return false;
185 } else if (makeGRRef(index, q2) && makei32(scale, q1)) {
186 if (scale < 1 || scale > 8 || ((1 << scale) & (0x116)) == 0) return false;
190 } else if (makeGRRef(index, summands[1])) {
194 if (ix < summands.size()) {
195 if (!makei32(offset, summands[ix])) return false;
198 if (ix != summands.size()) return false;
200 Ref<MemoryReference> ptr = memstream->alloc();
201 if (index.isNull()) {
202 ptr->setBaseAndOffset(unconst(base._ptr), offset);
204 ptr->setBaseIndexAndOffset(unconst(base._ptr), unconst(index._ptr), scale, offset);
207 //printf("mem: %p, %p, %d, %d\n", m._ptr->regs.base, m._ptr->regs.index, m._ptr->offset, m._ptr->modeAndScale);