Skip to content

Instantly share code, notes, and snippets.

@csaftoiu
Created May 13, 2015 19:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save csaftoiu/51b75a0f504c9fd485ca to your computer and use it in GitHub Desktop.
Save csaftoiu/51b75a0f504c9fd485ca to your computer and use it in GitHub Desktop.
Output of assembling isprime.golf
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#define MAX_RECURSION 1024
#define MAX_HEAP (64*1024*1024)
#define MAX_STACK (64*1024*1024)
#ifdef __GNUC__
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif
#define DATA_START UINT64_C(0x2000000000000000)
#define STACK_START UINT64_C(0x1000000000000000)
#define HEAP_START UINT64_C(0x0000000000000000)
#define IO_ADDR UINT64_C(0xffffffffffffffff)
struct registers
{
uint64_t a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
};
struct registers call_stack_regs[MAX_RECURSION];
void *call_stack_returns[MAX_RECURSION];
size_t call_stack_i = 0;
struct registers regs;
uint8_t *stack, *heap;
#define DATA_LEN 0
uint8_t data[DATA_LEN] = {};
uint64_t cycles = 0;
void init()
{
memset(&regs, 0, sizeof(regs));
regs.z = UINT64_C(0x1000000000000000);
stack = (uint8_t *)malloc(MAX_STACK);
heap = (uint8_t *)malloc(MAX_HEAP);
}
void halt(int a)
{
fprintf(stderr, "Ran for %"PRIu64" cycles\n", cycles);
exit(a);
}
static inline void mult64to128(uint64_t op1, uint64_t op2, uint64_t *hi, uint64_t *lo)
{
uint64_t u1 = (op1 & 0xffffffff);
uint64_t v1 = (op2 & 0xffffffff);
uint64_t t = (u1 * v1);
uint64_t w3 = (t & 0xffffffff);
uint64_t k = (t >> 32);
op1 >>= 32;
t = (op1 * v1) + k;
k = (t & 0xffffffff);
uint64_t w1 = (t >> 32);
op2 >>= 32;
t = (u1 * op2) + k;
k = (t >> 32);
*hi = (op1 * op2) + w1 + k;
*lo = (t << 32) + w3;
}
static inline void store(uint64_t address, uint64_t value, int width)
{
if (address == IO_ADDR)
{
if (width != 8)
{
fprintf(stderr, "May only use lw/sw for stdin/stdout");
exit(1);
}
putchar((char)(value & 0xff));
fflush(stdout);
return;
}
uint8_t *storep;
if (unlikely(address >= DATA_START))
{
fprintf(stderr, "Attempt to store in read-only data section");
exit(1);
}
else if (address >= STACK_START)
{
address -= STACK_START;
if (unlikely(address+width >= MAX_STACK))
{
fprintf(stderr, "Store outside of stack");
exit(1);
}
storep = &stack[address];
}
else
{
if (unlikely(address+width >= MAX_HEAP))
{
fprintf(stderr, "Store outside of heap");
exit(1);
}
storep = &heap[address];
}
switch (width) {
case 8: *(storep+7) = (uint8_t)(value >> 56);
*(storep+6) = (uint8_t)(value >> 48);
*(storep+5) = (uint8_t)(value >> 40);
*(storep+4) = (uint8_t)(value >> 32);
case 4: *(storep+3) = (uint8_t)(value >> 24);
*(storep+2) = (uint8_t)(value >> 16);
case 2: *(storep+1) = (uint8_t)(value >> 8);
case 1: *(storep ) = (uint8_t)(value );
}
}
static inline uint64_t load(uint64_t address, int width)
{
if (address == IO_ADDR)
{
if (width != 8)
{
fprintf(stderr, "May only use lw/sw for stdin/stdout");
exit(1);
}
return getchar();
}
uint8_t *loadp;
if (address >= DATA_START)
{
address -= DATA_START;
if (unlikely(address+width >= DATA_LEN))
{
fprintf(stderr, "Load outside of data");
exit(1);
}
loadp = &data[address];
}
else if (address >= STACK_START)
{
address -= STACK_START;
if (unlikely(address+width >= MAX_STACK))
{
fprintf(stderr, "Load outside of stack");
exit(1);
}
loadp = &stack[address];
}
else
{
if (unlikely(address+width >= MAX_HEAP))
{
fprintf(stderr, "Load outside of heap");
exit(1);
}
loadp = &heap[address];
}
uint64_t result = 0;
switch (width) {
case 8: result += (uint64_t)(*(loadp+7)) << 56;
result += (uint64_t)(*(loadp+6)) << 48;
result += (uint64_t)(*(loadp+5)) << 40;
result += (uint64_t)(*(loadp+4)) << 32;
case 4: result += (uint64_t)(*(loadp+3)) << 24;
result += (uint64_t)(*(loadp+2)) << 16;
case 2: result += (uint64_t)(*(loadp+1)) << 8;
case 1: result += (uint64_t)(*(loadp )) ;
}
return result;
}
int main(int argc, char **argv)
{
init();
// call main
cycles += 1;
call_stack_regs[call_stack_i] = regs;
call_stack_returns[call_stack_i] = &&__ret_to_0;
call_stack_i++;
goto main;
__ret_to_0:
// pop a, z
cycles += 6;
regs.z -= 8; regs.a = load(regs.z, 8);
// halt a
cycles += 0;
halt(regs.a);
readint:
// mov a, 0
cycles += 1;
regs.a = 0;
read_loop_start:
// call getchar
cycles += 1;
call_stack_regs[call_stack_i] = regs;
call_stack_returns[call_stack_i] = &&__ret_to_10;
call_stack_i++;
goto getchar;
__ret_to_10:
// pop b, z
cycles += 6;
regs.z -= 8; regs.b = load(regs.z, 8);
// mov c, b
cycles += 1;
regs.c = regs.b;
// cmp d, c, 10
cycles += 1;
regs.d = regs.c == 10;
// sub k, 0, 1
cycles += 1;
regs.k = 0 - 1;
// cmp i, c, k
cycles += 1;
regs.i = regs.c == regs.k;
// or e, d, i
cycles += 1;
regs.e = regs.d | regs.i;
// jz __examples_isprime_golfc_else_0, e
cycles += 1;
if (!regs.e) goto __examples_isprime_golfc_else_0;
// push z, a
cycles += 2;
store(regs.z, regs.a, 8); regs.z += 8;
// ret
cycles += 1;
{
struct registers tmp = regs;
regs = call_stack_regs[call_stack_i - 1];
regs.z = tmp.z;
void *ret_addr = call_stack_returns[call_stack_i - 1];
call_stack_i--;
goto *ret_addr;
}
__examples_isprime_golfc_else_0:
// mul n, s, 10, a
cycles += 3;
mult64to128(10, regs.a, &regs.s, &regs.n);
// sub r, c, 48
cycles += 1;
regs.r = regs.c - 48;
// add o, n, r
cycles += 1;
regs.o = regs.n + regs.r;
// mov a, o
cycles += 1;
regs.a = regs.o;
// jmp read_loop_start
cycles += 1;
goto read_loop_start;
// ret
cycles += 1;
{
struct registers tmp = regs;
regs = call_stack_regs[call_stack_i - 1];
regs.z = tmp.z;
void *ret_addr = call_stack_returns[call_stack_i - 1];
call_stack_i--;
goto *ret_addr;
}
main:
// call readint
cycles += 1;
call_stack_regs[call_stack_i] = regs;
call_stack_returns[call_stack_i] = &&__ret_to_35;
call_stack_i++;
goto readint;
__ret_to_35:
// pop c, z
cycles += 6;
regs.z -= 8; regs.c = load(regs.z, 8);
// mov a, c
cycles += 1;
regs.a = regs.c;
// cmp b, a, 2
cycles += 1;
regs.b = regs.a == 2;
// jz __examples_isprime_golfc_else_1, b
cycles += 1;
if (!regs.b) goto __examples_isprime_golfc_else_1;
// jmp prime
cycles += 1;
goto prime;
__examples_isprime_golfc_else_1:
// div k, f, a, 2
cycles += 10;
regs.k = regs.a / 2;
regs.f = regs.a % 2;
// cmp g, f, 0
cycles += 1;
regs.g = regs.f == 0;
// jz __examples_isprime_golfc_else_2, g
cycles += 1;
if (!regs.g) goto __examples_isprime_golfc_else_2;
// jmp notprime
cycles += 1;
goto notprime;
__examples_isprime_golfc_else_2:
// mov m, 3
cycles += 1;
regs.m = 3;
loopstart:
// mul o, p, m, m
cycles += 3;
mult64to128(regs.m, regs.m, &regs.p, &regs.o);
// leq l, o, a
cycles += 1;
regs.l = (int64_t)regs.o <= (int64_t)regs.a;
// jz __examples_isprime_golfc_else_3, l
cycles += 1;
if (!regs.l) goto __examples_isprime_golfc_else_3;
// div v, u, a, m
cycles += 10;
regs.v = regs.a / regs.m;
regs.u = regs.a % regs.m;
// cmp r, u, 0
cycles += 1;
regs.r = regs.u == 0;
// jz __examples_isprime_golfc_else_4, r
cycles += 1;
if (!regs.r) goto __examples_isprime_golfc_else_4;
notprime:
// push z, 110
cycles += 2;
store(regs.z, 110, 8); regs.z += 8;
// call putchar
cycles += 1;
call_stack_regs[call_stack_i] = regs;
call_stack_returns[call_stack_i] = &&__ret_to_63;
call_stack_i++;
goto putchar;
__ret_to_63:
// pop c, z
cycles += 6;
regs.z -= 8; regs.c = load(regs.z, 8);
// push z, 10
cycles += 2;
store(regs.z, 10, 8); regs.z += 8;
// call putchar
cycles += 1;
call_stack_regs[call_stack_i] = regs;
call_stack_returns[call_stack_i] = &&__ret_to_66;
call_stack_i++;
goto putchar;
__ret_to_66:
// pop e, z
cycles += 6;
regs.z -= 8; regs.e = load(regs.z, 8);
// push z, 0
cycles += 2;
store(regs.z, 0, 8); regs.z += 8;
// ret
cycles += 1;
{
struct registers tmp = regs;
regs = call_stack_regs[call_stack_i - 1];
regs.z = tmp.z;
void *ret_addr = call_stack_returns[call_stack_i - 1];
call_stack_i--;
goto *ret_addr;
}
__examples_isprime_golfc_else_4:
// add g, m, 2
cycles += 1;
regs.g = regs.m + 2;
// mov m, g
cycles += 1;
regs.m = regs.g;
// jmp loopstart
cycles += 1;
goto loopstart;
__examples_isprime_golfc_else_3:
prime:
// push z, 121
cycles += 2;
store(regs.z, 121, 8); regs.z += 8;
// call putchar
cycles += 1;
call_stack_regs[call_stack_i] = regs;
call_stack_returns[call_stack_i] = &&__ret_to_78;
call_stack_i++;
goto putchar;
__ret_to_78:
// pop k, z
cycles += 6;
regs.z -= 8; regs.k = load(regs.z, 8);
// push z, 10
cycles += 2;
store(regs.z, 10, 8); regs.z += 8;
// call putchar
cycles += 1;
call_stack_regs[call_stack_i] = regs;
call_stack_returns[call_stack_i] = &&__ret_to_81;
call_stack_i++;
goto putchar;
__ret_to_81:
// pop l, z
cycles += 6;
regs.z -= 8; regs.l = load(regs.z, 8);
// push z, 0
cycles += 2;
store(regs.z, 0, 8); regs.z += 8;
// ret
cycles += 1;
{
struct registers tmp = regs;
regs = call_stack_regs[call_stack_i - 1];
regs.z = tmp.z;
void *ret_addr = call_stack_returns[call_stack_i - 1];
call_stack_i--;
goto *ret_addr;
}
// ret
cycles += 1;
{
struct registers tmp = regs;
regs = call_stack_regs[call_stack_i - 1];
regs.z = tmp.z;
void *ret_addr = call_stack_returns[call_stack_i - 1];
call_stack_i--;
goto *ret_addr;
}
putchar:
// pop a, z # int a
cycles += 6;
regs.z -= 8; regs.a = load(regs.z, 8);
// sw -1, a
cycles += 1;
store(-1, regs.a, 8);
// push z, 0 # return 0
cycles += 2;
store(regs.z, 0, 8); regs.z += 8;
// ret
cycles += 1;
{
struct registers tmp = regs;
regs = call_stack_regs[call_stack_i - 1];
regs.z = tmp.z;
void *ret_addr = call_stack_returns[call_stack_i - 1];
call_stack_i--;
goto *ret_addr;
}
getchar:
// lw a, -1
cycles += 5;
regs.a = load(-1, 8);
// push z, a
cycles += 2;
store(regs.z, regs.a, 8); regs.z += 8;
// ret
cycles += 1;
{
struct registers tmp = regs;
regs = call_stack_regs[call_stack_i - 1];
regs.z = tmp.z;
void *ret_addr = call_stack_returns[call_stack_i - 1];
call_stack_i--;
goto *ret_addr;
}
halt(0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment