Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
bf.cpp
Go to the documentation of this file.
1#define XBYAK_NO_OP_NAMES
2#include "xbyak/xbyak.h"
3#include <stdio.h>
4#include <stdlib.h>
5#include <stack>
6#include <fstream>
7#ifdef _MSC_VER
8 #pragma warning(disable : 4996) // scanf
9 #define snprintf _snprintf_s
10#endif
11
13private:
14 enum Direction { B, F };
15 std::string toStr(int labelNo, Direction dir)
16 {
17 return Xbyak::Label::toStr(labelNo) + (dir == B ? 'B' : 'F');
18 }
19public:
20 int getContinuousChar(std::istream& is, char c)
21 {
22 int count = 1;
23 char p;
24 while (is >> p) {
25 if (p != c) break;
26 count++;
27 }
28 is.unget();
29 return count;
30 }
31 Brainfuck(std::istream& is) : CodeGenerator(100000)
32 {
33 // void (*)(void* putchar, void* getchar, int *stack)
34 using namespace Xbyak;
35#ifdef XBYAK32
36 const Reg32& pPutchar(esi);
37 const Reg32& pGetchar(edi);
38 const Reg32& stack(ebp);
39 const Address cur = dword [stack];
40 push(ebp); // stack
41 push(esi);
42 push(edi);
43 const int P_ = 4 * 3;
44 mov(pPutchar, ptr[esp + P_ + 4]); // putchar
45 mov(pGetchar, ptr[esp + P_ + 8]); // getchar
46 mov(stack, ptr[esp + P_ + 12]); // stack
47#elif defined(XBYAK64_WIN)
48 const Reg64& pPutchar(rsi);
49 const Reg64& pGetchar(rdi);
50 const Reg64& stack(rbp); // stack
51 const Address cur = dword [stack];
52 push(rsi);
53 push(rdi);
54 push(rbp);
55 mov(pPutchar, rcx); // putchar
56 mov(pGetchar, rdx); // getchar
57 mov(stack, r8); // stack
58#else
59 const Reg64& pPutchar(rbx);
60 const Reg64& pGetchar(rbp);
61 const Reg64& stack(r12); // stack
62 const Address cur = dword [stack];
63 push(rbx);
64 push(rbp);
65 push(r12);
66 mov(pPutchar, rdi); // putchar
67 mov(pGetchar, rsi); // getchar
68 mov(stack, rdx); // stack
69#endif
70 int labelNo = 0;
71 std::stack<int> keepLabelNo;
72 char c;
73 while (is >> c) {
74 switch (c) {
75 case '+':
76 case '-':
77 {
78 int count = getContinuousChar(is, c);
79 if (count == 1) {
80 c == '+' ? inc(cur) : dec(cur);
81 } else {
82 add(cur, (c == '+' ? count : -count));
83 }
84 }
85 break;
86 case '>':
87 case '<':
88 {
89 int count = getContinuousChar(is, c);
90 add(stack, 4 * (c == '>' ? count : -count));
91 }
92 break;
93 case '.':
94#ifdef XBYAK32
95 push(cur);
96 call(pPutchar);
97 pop(eax);
98#elif defined(XBYAK64_WIN)
99 mov(ecx, cur);
100 sub(rsp, 32);
101 call(pPutchar);
102 add(rsp, 32);
103#else
104 mov(edi, cur);
105 call(pPutchar);
106#endif
107 break;
108 case ',':
109#if defined(XBYAK32) || defined(XBYAK64_GCC)
110 call(pGetchar);
111#elif defined(XBYAK64_WIN)
112 sub(rsp, 32);
113 call(pGetchar);
114 add(rsp, 32);
115#endif
116 mov(cur, eax);
117 break;
118 case '[':
119 L(toStr(labelNo, B));
120 mov(eax, cur);
121 test(eax, eax);
122 jz(toStr(labelNo, F), T_NEAR);
123 keepLabelNo.push(labelNo++);
124 break;
125 case ']':
126 {
127 int no = keepLabelNo.top(); keepLabelNo.pop();
128 jmp(toStr(no, B));
129 L(toStr(no, F));
130 }
131 break;
132 default:
133 break;
134 }
135 }
136#ifdef XBYAK32
137 pop(edi);
138 pop(esi);
139 pop(ebp);
140#elif defined(XBYAK64_WIN)
141 pop(rbp);
142 pop(rdi);
143 pop(rsi);
144#else
145 pop(r12);
146 pop(rbp);
147 pop(rbx);
148#endif
149 ret();
150 }
151};
152
153void dump(const Xbyak::uint8 *code, size_t size)
154{
155 puts("#include <stdio.h>\nstatic int stack[128 * 1024];");
156#ifdef _MSC_VER
157 printf("static __declspec(align(4096)) ");
158#else
159 printf("static __attribute__((aligned(4096)))");
160#endif
161 puts("const unsigned char code[] = {");
162 for (size_t i = 0; i < size; i++) {
163 printf("0x%02x,", code[i]); if ((i % 16) == 15) putchar('\n');
164 }
165 puts("\n};");
166#ifdef _MSC_VER
167 puts("#include <windows.h>");
168#else
169 puts("#include <unistd.h>");
170 puts("#include <sys/mman.h>");
171#endif
172 puts("int main()\n{");
173#ifdef _MSC_VER
174 puts("\tDWORD oldProtect;");
175 puts("\tVirtualProtect((void*)code, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtect);");
176#else
177 puts("\tlong pageSize = sysconf(_SC_PAGESIZE) - 1;");
178 puts("\tmprotect((void*)code, (sizeof(code) + pageSize) & ~pageSize, PROT_READ | PROT_EXEC);");
179#endif
180 puts(
181 "\t((void (*)(void*, void*, int *))code)((void*)putchar, (void*)getchar, stack);\n"
182 "}"
183 );
184}
185
186int main(int argc, char *argv[])
187{
188#ifdef XBYAK32
189 fprintf(stderr, "32bit mode\n");
190#else
191 fprintf(stderr, "64bit mode\n");
192#endif
193 if (argc == 1) {
194 fprintf(stderr, "bf filename.bf [0|1]\n");
195 return 1;
196 }
197 std::ifstream ifs(argv[1]);
198 int mode = argc == 3 ? atoi(argv[2]) : 0;
199 try {
200 Brainfuck bf(ifs);
201 if (mode == 0) {
202 static int stack[128 * 1024];
203 bf.getCode<void (*)(void*, void*, int *)>()(Xbyak::CastTo<void*>(putchar), Xbyak::CastTo<void*>(getchar), stack);
204 } else {
205 dump(bf.getCode(), bf.getSize());
206 }
207 } catch (std::exception& e) {
208 printf("ERR:%s\n", e.what());
209 } catch (...) {
210 printf("unknown error\n");
211 }
212}
213
void dump(const Xbyak::uint8 *code, size_t size)
Definition bf.cpp:153
const mie::Vuint & p
Definition bn.cpp:27
Brainfuck(std::istream &is)
Definition bf.cpp:31
int getContinuousChar(std::istream &is, char c)
Definition bf.cpp:20
size_t getSize() const
Definition xbyak.h:911
const uint8 * getCode() const
Definition xbyak.h:905
void call(const Operand &op)
Definition xbyak.h:2150
const Reg32 esp
Definition xbyak.h:2087
const Reg32 eax
Definition xbyak.h:2087
const AddressFrame dword
Definition xbyak.h:2090
void jmp(const Operand &op)
Definition xbyak.h:2144
void inc(const Operand &op)
Definition xbyak.h:307
const Reg32 ecx
Definition xbyak.h:2087
void test(const Operand &op, const Reg &reg)
Definition xbyak.h:2162
const Reg32 ebp
Definition xbyak.h:2087
void add(const Operand &op, uint32 imm)
Definition xbyak.h:6
void sub(const Operand &op, uint32 imm)
Definition xbyak.h:746
const Reg32 edi
Definition xbyak.h:2087
void jz(const Label &label, LabelType type=T_AUTO)
Definition xbyak.h:425
void mov(const Operand &reg1, const Operand &reg2)
Definition xbyak.h:2210
void pop(const Operand &op)
Definition xbyak.h:2190
const Reg32 esi
Definition xbyak.h:2087
void L(const std::string &label)
Definition xbyak.h:2126
void push(const Operand &op)
Definition xbyak.h:2189
void dec(const Operand &op)
Definition xbyak.h:162
const AddressFrame ptr
Definition xbyak.h:2090
static std::string toStr(int num)
Definition xbyak.h:1103
int * count
char ** argv
Definition xbyak.h:104
const To CastTo(From p)
Definition xbyak.h:279
Xbyak ; JIT assembler for x86(IA32)/x64 by C++.
CK_RV ret