lsnes rr2-β23
[lsnes.git] / include / library / assembler.hpp
blob671764d401f96944e11c3e0e8c5a36d309b31137
1 #ifndef _library__assembler__hpp__included__
2 #define _library__assembler__hpp__included__
4 #include <cstring>
5 #include "serialization.hpp"
6 #include <cstdint>
7 #include <stdexcept>
8 #include <functional>
9 #include <map>
10 #include <vector>
11 #include <list>
13 namespace assembler
15 typedef size_t addr_t;
16 class label
18 public:
19 label()
21 kind = L_LOCAL_U;
23 label(void* global)
25 kind = L_GLOBAL;
26 addr = (addr_t)global;
28 label(const label& _base, int off)
30 switch(_base.kind) {
31 case L_LOCAL_U:
32 base = &_base;
33 offset = off;
34 kind = L_RELATIVE;
35 break;
36 case L_LOCAL_R:
37 offset = _base.offset + off;
38 kind = L_LOCAL_R;
39 break;
40 case L_GLOBAL:
41 addr = _base.addr + off;
42 kind = L_GLOBAL;
43 break;
44 case L_RELATIVE:
45 base = _base.base;
46 offset = _base.offset + off;
47 kind = L_RELATIVE;
48 break;
51 void set(int off)
53 if(kind != L_LOCAL_U)
54 throw std::runtime_error("Not undefined local label");
55 offset = off;
56 kind = L_LOCAL_R;
58 addr_t resolve(addr_t localbase) const
60 switch(kind) {
61 case L_LOCAL_U: throw std::runtime_error("Unresolved label");
62 case L_LOCAL_R: return localbase + offset;
63 case L_GLOBAL: return addr;
64 case L_RELATIVE: return base->resolve(localbase) + offset;
66 throw std::runtime_error("Unknown relocation type");
68 private:
69 enum _kind { L_LOCAL_U, L_LOCAL_R, L_GLOBAL, L_RELATIVE } kind;
70 const struct label* base;
71 addr_t addr;
72 int offset;
75 class label_list
77 public:
78 operator label&();
79 operator label*();
80 label& external(void* addr);
81 private:
82 std::list<label> labels;
85 void i386_reloc_rel8(uint8_t* location, size_t target, size_t source);
86 void i386_reloc_rel16(uint8_t* location, size_t target, size_t source);
87 void i386_reloc_rel32(uint8_t* location, size_t target, size_t source);
88 void i386_reloc_abs32(uint8_t* location, size_t target, size_t source);
89 void i386_reloc_abs64(uint8_t* location, size_t target, size_t source);
90 uint8_t i386_modrm(uint8_t reg, uint8_t mod, uint8_t rm);
91 uint8_t i386_sib(uint8_t base, uint8_t index, uint8_t scale);
93 struct pad_tag
95 pad_tag(size_t _amount) : amount(_amount) {}
96 size_t amount;
99 struct label_tag
101 label_tag(label& _l) : l(_l) {}
102 label& l;
105 struct relocation_tag
107 relocation_tag(std::function<void(uint8_t* location, size_t target, size_t source)> _promise,
108 const label& _target) : promise(_promise), target(_target) {}
109 std::function<void(uint8_t* location, size_t target, size_t source)> promise;
110 const label& target;
113 struct byteseq_tag
115 byteseq_tag(const uint8_t* ss, size_t _sl) { st.resize(_sl); memcpy(&st[0], ss, _sl); }
116 std::vector<uint8_t> st;
119 template<typename T> byteseq_tag vle(T v)
121 uint8_t b[sizeof(T)];
122 serialization::write_common<T, false>(b, v);
123 return byteseq_tag(b, sizeof(T));
126 template<typename T> byteseq_tag vbe(T v)
128 uint8_t b[sizeof(T)];
129 serialization::write_common<T, true>(b, v);
130 return byteseq_tag(b, sizeof(T));
133 struct assembler
135 assembler();
136 template<typename... T> void operator()(uint8_t b, T... args)
138 byte(b);
139 (*this)(args...);
141 template<typename... T> void operator()(pad_tag p, T... args)
143 pad(p.amount);
144 (*this)(args...);
146 template<typename... T> void operator()(label_tag l, T... args)
148 label(l.l);
149 (*this)(args...);
151 template<typename... T> void operator()(relocation_tag r, T... args)
153 relocation(r.promise, r.target);
154 (*this)(args...);
156 template<typename... T> void operator()(byteseq_tag b, T... args)
158 size_t o = size();
159 pad(b.st.size());
160 memcpy(&data[o], &b.st[0], b.st.size());
161 (*this)(args...);
163 void operator()() {}
165 void _label(label& l);
166 void _label(label& l, const std::string& globalname);
167 void byte(uint8_t b);
168 void byte(std::initializer_list<uint8_t> b);
169 void byte(const uint8_t* b, size_t l);
170 void relocation(std::function<void(uint8_t* location, size_t target, size_t source)> promise,
171 const label& target);
172 void align(size_t multiple);
173 void pad(size_t amount);
174 size_t size();
175 void dump(const std::string& basename, const std::string& name, void* base, std::map<std::string, void*> map);
176 std::map<std::string, void*> flush(void* base);
177 private:
178 struct reloc
180 std::function<void(uint8_t* location, size_t target, size_t source)> promise;
181 const label* target;
182 size_t source;
184 std::vector<uint8_t> data;
185 std::list<reloc> relocs;
186 std::map<std::string, const label*> globals;
189 class dynamic_code
191 public:
192 dynamic_code(size_t size);
193 ~dynamic_code();
194 void commit();
195 uint8_t* pointer() throw();
196 private:
197 void* base;
198 size_t asize;
203 #endif