Created
September 8, 2010 10:19
-
-
Save hogelog/569932 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <sstream> | |
#include <stack> | |
#define MEMSIZE 30000 | |
#define CODESIZE 30000 | |
#include "xbyak/xbyak.h" | |
class BFVM : public Xbyak::CodeGenerator { | |
private: | |
FILE *input; | |
int membuf[MEMSIZE]; | |
static const char* toLabel(char ch, int num) | |
{ | |
static std::stringstream labelStream; | |
labelStream.str(""); | |
labelStream << ch << num; | |
return labelStream.str().c_str(); | |
} | |
public: | |
BFVM(FILE *input) : | |
CodeGenerator(CODESIZE), | |
input(input) | |
{ | |
using namespace Xbyak; | |
push(ebx); | |
push(esi); | |
push(edi); | |
Reg32 mem(ebx); | |
Reg32 ptrGetchar(esi); | |
Reg32 ptrPutchar(edi); | |
mov(eax, 0); | |
mov(mem, (int) membuf); | |
mov(ptrGetchar, (int) getchar); | |
mov(ptrPutchar, (int) putchar); | |
char ch = 0, nextch = 0; | |
int opMemCount = 0; | |
int opPtrCount = 0; | |
std::stack<int> labelStack; | |
int labelNum = 0; | |
std::string label; | |
do { | |
nextch = getc(input); | |
switch(ch) { | |
case '+': | |
case '-': | |
opMemCount += ch=='+' ? 1 : -1; | |
if ((nextch!='+' && nextch!='-') && opMemCount!=0) { | |
switch(opMemCount) { | |
case 1: | |
inc(eax); | |
break; | |
case -1: | |
dec(eax); | |
break; | |
default: | |
add(eax, opMemCount); | |
break; | |
} | |
opMemCount = 0; | |
} | |
break; | |
case '>': | |
case '<': | |
opPtrCount += ch=='>' ? 1 : -1; | |
if ((nextch!='>' && nextch!='<') && opPtrCount!=0) { | |
mov(dword [mem], eax); | |
add(mem, 4*opPtrCount); | |
mov(eax, dword [mem]); | |
opPtrCount = 0; | |
} | |
break; | |
case ',': | |
call(ptrGetchar); | |
break; | |
case '.': | |
push(eax); | |
call(ptrPutchar); | |
pop(eax); | |
break; | |
case '[': | |
L(toLabel('L', labelNum)); | |
test(eax, eax); | |
jz(toLabel('R', labelNum), T_NEAR); | |
labelStack.push(labelNum); | |
++labelNum; | |
break; | |
case ']': | |
int beginNum = labelStack.top(); | |
labelStack.pop(); | |
jmp(toLabel('L', beginNum), T_NEAR); | |
L(toLabel('R', beginNum)); | |
break; | |
} | |
ch = nextch; | |
} while (ch != EOF); | |
pop(edi); | |
pop(esi); | |
pop(ebx); | |
ret(); | |
} | |
void execute() | |
{ | |
void (*codes)() = (void (*)()) getCode(); | |
codes(); | |
fflush(stdout); | |
fprintf(stderr, "\nsize of x86-code: %d\n", getSize()); | |
} | |
}; | |
int main() | |
{ | |
BFVM bf(stdin); | |
bf.execute(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment