summaryrefslogtreecommitdiff
path: root/skullfuck.c
diff options
context:
space:
mode:
authorjakob <jakob@memeware.net>2017-03-18 18:07:39 -0400
committerjakob <jakob@memeware.net>2017-03-18 18:07:39 -0400
commitd45dbeb48a9da2ccfc1dd3fc0f3baea4c365e086 (patch)
treed1107185a1b722ee65b2c8f9b5f70376dd39057a /skullfuck.c
parent9b5abf3e3859e54d4bc48db0792b2686eb7bd16a (diff)
The compilation process now includes *very* minimal code optimization.
Diffstat (limited to 'skullfuck.c')
-rw-r--r--skullfuck.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/skullfuck.c b/skullfuck.c
index 7d9e0a8..b40e903 100644
--- a/skullfuck.c
+++ b/skullfuck.c
@@ -29,9 +29,13 @@
#define ARCH "x86_64"
#define OS "Linux"
#define INC_DATA_PTR "\tincq %rsi\n"
+#define ADD_DATA_PTR "\taddq $0x%x, %%rsi\n"
#define DEC_DATA_PTR "\tdecq %rsi\n"
+#define SUB_DATA_PTR "\tsubq $0x%x, %%rsi\n"
#define INC_DATA "\tincb (%rsi)\n"
+#define ADD_DATA "\taddb $0x%x, (%%rsi)\n"
#define DEC_DATA "\tdecb (%rsi)\n"
+#define SUB_DATA "\tsubb $0x%x, (%%rsi)\n"
#define PRINT_DATA "\tmovq $0x01, %rax\n" \
"\tmovq $0x01, %rdi\n" \
"\tsyscall\n"
@@ -58,9 +62,13 @@
#define ARCH "i686"
#define OS "Linux"
#define INC_DATA_PTR "\tincl %ecx\n"
+#define ADD_DATA_PTR "\taddl $0x%x, %%ecx\n"
#define DEC_DATA_PTR "\tdecl %ecx\n"
+#define SUB_DATA_PTR "\tsubl $0x%x, %%ecx\n"
#define INC_DATA "\tincb (%ecx)\n"
+#define ADD_DATA "\taddb $0x%x, (%%ecx)\n"
#define DEC_DATA "\tdecb (%ecx)\n"
+#define SUB_DATA "\tsubb $0x%x, (%%ecx)\n"
#define PRINT_DATA "\tmovl $0x04, %eax\n" \
"\tmovl $0x01, %ebx\n" \
"\tint $0x80\n"
@@ -121,26 +129,57 @@ static int pop_loop_index(struct loop_stack *s) {
}
+/* Minor optimization subroutine. Increments the `in` pointer to beyond
+ the collection of adjacent `op` characters, and returns the number
+ of operations counted. */
+static int reduce(char **in, char op) {
+ int i;
+ for (i = 0; (*in)[i] == op; i++);
+ *in += i - 1;
+ return i;
+}
+
+
/* Converts the brainfuck instructions read from `in` to assembly
instructions and writes them to `out`. `in` is expected to be
null-terminated. */
static void write_instructions(FILE *out, char *in) {
- int next_loop = 0, cur_loop = 0;
+ int next_loop = 0, cur_loop = 0, op_count;
struct loop_stack *loops = calloc(sizeof(struct loop_stack), 1);
for (char *cur = in; *cur != '\0'; cur++) {
switch(*cur) {
case '>':
- fputs(INC_DATA_PTR, out);
+ op_count = reduce(&cur, '>');
+ if (op_count > 1) {
+ fprintf(out, ADD_DATA_PTR, op_count);
+ } else {
+ fputs(INC_DATA_PTR, out);
+ }
break;
case '<':
- fputs(DEC_DATA_PTR, out);
+ op_count = reduce(&cur, '<');
+ if (op_count > 1) {
+ fprintf(out, SUB_DATA_PTR, op_count);
+ } else {
+ fputs(DEC_DATA_PTR, out);
+ }
break;
case '+':
- fputs(INC_DATA, out);
+ op_count = reduce(&cur, '+');
+ if (op_count > 1) {
+ fprintf(out, ADD_DATA, op_count);
+ } else {
+ fputs(INC_DATA, out);
+ }
break;
case '-':
- fputs(DEC_DATA, out);
+ op_count = reduce(&cur, '-');
+ if (op_count > 1) {
+ fprintf(out, SUB_DATA, op_count);
+ } else {
+ fputs(DEC_DATA, out);
+ }
break;
case '.':
fputs(PRINT_DATA, out);
@@ -223,6 +262,10 @@ static void create_binary(struct params p) {
wait(NULL);
}
}
+
+ if (!p.compile_only)
+ remove("/tmp/skullfuck_tmp.s");
+ remove("/tmp/skullfuck_tmp.o");
}