#include #include #include #pragma clang diagnostic ignored "-Wparentheses" #pragma clang diagnostic ignored "-Wreturn-type" #pragma clang diagnostic ignored "-Wempty-body" // pu2! // maybe compacter? idk #define A 8 // change this for error reporting on unknown instructions! // examples: // #define A __builtin_trap() // ^ does SIGTRAP // #define A my_custom_cpu_error_trap() // ^ calls my_custom_cpu_error_trap() #define __PU2_SPEED_IMPROVEMENT #define __PU2_EXTENDED_INSTRUCTION_SET #define S (1 << 25) #define J while #define H !--c #ifndef __PU2_SPEED_IMPROVEMENT #ifndef __PU2_EXTENDED_INSTRUCTION_SET // clang-format off m[S],c,v,a,b,u;pu2(){J(c=m[m[7]++],v=m[m[7]++],c){H?a=v:H?a=m[b]:H?u?m[a]=b:0:H?v=a,a=b,b=v:H?a+=b:H?a-=b:H?a&=b:H?a=!a:H?u=v:H?u=a:H?a=u:H?u=b:H?b=u:A;}} // clang-format on #else // clang-format off m[S],c,v,a,b,u;pu2(){J(c=m[m[7]++],v=m[m[7]++],c){H?a=v:H?a=m[b]:H?u?m[a]=b:0:H?v=a,a=b,b=v:H?a+=b:H?a-=b:H?a&=b:H?a=!a:H?u=v:H?u=a:H?a=u:H?u=b:H?b=u:H?m[0]+=v*2:H?m[v]=m[a]:H?a=m[v]:H?m[a]=v:H?m[a]=m[v]:A;}} // clang-format on #endif #else #include #undef A #define A \ ({ \ printf("ERROR: Invalid instruction!\n"); \ exit(1); \ }) // pu2 optimized for speed implements a few new instructions for speed, // and has a "bake" mode which will preprocess the memory and perform the required modifications. // // 14: nop // 15: m[imm] = m[a] // 16: a = m[imm] // 17: m[a] = imm // 18: m[a] = m[imm] // not implemented yet, was lazy // bake(int start, int end) {} __attribute__((aligned(64))) m[ S ], a, b, u, c; typedef struct { int c; int v; } vminst; pu2() { vminst *M = (vminst *) m; int s1, s2, s3; const __attribute__((aligned(64))) void *PRECOMPUTED_TABLE[] = { &&C_ZERO, &&C_ONE, &&C_TWO, &&C_THREE, &&C_FOUR, &&C_FIVE, &&C_SIX, &&C_SEVEN, &&C_EIGHT, &&C_NINE, &&C_TEN, &&C_ELEVEN, &&C_TWELVE, &&C_THIRTEEN, &&CB_FOURTEEN, &&CB_FIFTEEN, &&CB_SIXTEEN, &&CB_SEVENTEEN, &&CB_EIGHTEEN }; int pc = m[ 7 ] >> 1; register vminst inst; J(inst = M[ pc++ ], inst.c) { if (__builtin_expect(inst.c > 18, 0)) A; goto *PRECOMPUTED_TABLE[ inst.c ]; C_ZERO: break; C_ONE: a = inst.v; continue; C_TWO: a = m[ b ]; continue; C_THREE: if (u) { if (__builtin_expect(a == 7, 0)) pc = b >> 1; m[ a ] = b; } continue; C_FOUR: s1 = a; a = b; b = s1; continue; C_FIVE: a += b; continue; C_SIX: a -= b; continue; C_SEVEN: a = !a; continue; C_EIGHT: u = inst.v; continue; C_NINE: u = inst.v; continue; C_TEN: u = a; continue; C_ELEVEN: a = u; continue; C_TWELVE: u = b; continue; C_THIRTEEN: b = u; continue; CB_FOURTEEN: // nop // this instruction allows for essentially embedding data inside a program, as pu2 will skip // right over it pc += inst.v; continue; CB_FIFTEEN: if (__builtin_expect(inst.v == 7, 0)) pc = m[ a ] >> 1; m[ inst.v ] = m[ a ]; continue; CB_SIXTEEN: a = m[ inst.v ]; continue; CB_SEVENTEEN: if (__builtin_expect(a == 7, 0)) pc = inst.v >> 1; m[ a ] = inst.v; continue; CB_EIGHTEEN: if (__builtin_expect(a == 7, 0)) pc = m[ inst.v ] >> 1; m[ a ] = m[ inst.v ]; continue; } m[ 7 ] = pc << 1; } #endif // there's just memory. no, really // ok actually there's c_one registers called a and b // 0 HLT: halt // 1 IMM: a = imm // 2 LOD: a = m[b] // 3 STR: m[a] = b (only happens if acc != 0) // 4 SWP: swap a and b // 5 ADD: a += b // 6 SUB: a -= b // 7 AND: a &= b // 8 NOT: a = !a // 9 ACC: u = imm // 10 A2U: u = a // 11 U2A: a = u // 12 B2U: u = b // 13 U2B: b = u // NOTE: Memory indexes less than 1024 should be considered as temporary/compute memory, and // programs should be written at index 1024 and upwards. // // NOTE: Memory index 7 is the program // counter, in which the current instruction is read from m[m[7]] at each cycle // ------------------------- // yeehaw baby it's time for as2 // E is the error code loc. zero it before calling as2 // Y is macro storage. extend as needed // set O for output before running. keep in mind, it gets modified whilst as2 is running. // therefore, i recommend you store a copy somewhere! // clang-format off char*C="hltimmlodstrswpaddsubandnotacca2uu2ab2uu2bnopcb1cb2cb3",*Y[1<<10],*E,*L,i;*K;as2(char*I){J(c=*I++){if(c==35){J(*++I-10);c=*I++;}L=C;(!isspace(c)?c-39?c-125?c-123?c-64?({i=0,I--;J(i++,*L)strncmp(L,I,3)?L+=3:({I+=3;*K++=i-1;*K++=(i-2&&i-9)?0:strtol(I,&I,10);goto Q;});E=I;return 1;Q:;}):as2(Y[strtol(I,&I,10)]):({Y[strtol(I,&I,10)]=I+1;J(*I++-125);}):({break;}):({*K++=1;*K++=*I++;}):0);}} // clang-format on // #undef S #undef H #undef J #undef E