|
| 1 | +/* cisc.h |
| 2 | + * Mock-assembly programming for a CISC-like architecture |
| 3 | + * |
| 4 | + * Programmer: Mayer Goldberg, 2015 |
| 5 | + */ |
| 6 | + |
| 7 | +#include <stdio.h> |
| 8 | +#include <stdlib.h> |
| 9 | + |
| 10 | +#define Bytes(n) (n) |
| 11 | +#define Kilo(n) (Bytes(n) << 10) |
| 12 | +#define Mega(n) (Kilo(n) << 10) |
| 13 | +#define Giga(n) (Mega(n) << 10) |
| 14 | + |
| 15 | +#define RAM_SIZE Mega(400)//Giga(1) |
| 16 | +#define STACK_SIZE Mega(400)//Giga(1) |
| 17 | + |
| 18 | +#define WORD_SIZE (sizeof(long)) |
| 19 | + |
| 20 | +typedef struct Machine { |
| 21 | + long mem[RAM_SIZE]; |
| 22 | + long stack[STACK_SIZE]; |
| 23 | + long r0, r1, r2, r3, r4, r5, r6, r7, |
| 24 | + r8, r9, r10, r11, r12, r13, r14, r15; |
| 25 | + long sp, fp; |
| 26 | + long test_result; |
| 27 | +} Machine; |
| 28 | + |
| 29 | +extern Machine *machine; |
| 30 | + |
| 31 | +#define M(p) (machine->p) |
| 32 | + |
| 33 | +#define L(x) ((long)(x)) |
| 34 | +#define LP(x) ((long *)(x)) |
| 35 | +#define LPR(x) (*LP(x)) |
| 36 | + |
| 37 | +#define R0 (M(r0)) |
| 38 | +#define R1 (M(r1)) |
| 39 | +#define R2 (M(r2)) |
| 40 | +#define R3 (M(r3)) |
| 41 | +#define R4 (M(r4)) |
| 42 | +#define R5 (M(r5)) |
| 43 | +#define R6 (M(r6)) |
| 44 | +#define R7 (M(r7)) |
| 45 | +#define R8 (M(r8)) |
| 46 | +#define R9 (M(r9)) |
| 47 | +#define R10 (M(r10)) |
| 48 | +#define R11 (M(r11)) |
| 49 | +#define R12 (M(r12)) |
| 50 | +#define R13 (M(r13)) |
| 51 | +#define R14 (M(r14)) |
| 52 | +#define R15 (M(r15)) |
| 53 | +#define SP (M(sp)) |
| 54 | +#define FP (M(fp)) |
| 55 | + |
| 56 | +#define IMM(n) (L(n)) |
| 57 | +#define IND(r) (M(mem)[(r)]) |
| 58 | +#define INDD(r, d) (M(mem)[(r) + (d)]) |
| 59 | +#define ADDR(r) (IND(r)) /* ADDR(n) == IND(n) */ |
| 60 | +#define STACK(n) (M(stack)[(n)]) |
| 61 | +#define STARG(n) (STACK(SP-(n)-2)) |
| 62 | +#define FPARG(n) (STACK(FP-(n)-3)) |
| 63 | +#define LOCAL(n) (STACK(FP+(n))) |
| 64 | +#define LABEL(l) (L(&&l)) |
| 65 | + |
| 66 | +/* definition of the opcodes */ |
| 67 | + |
| 68 | +#define CMP(x, y) (M(test_result) = ((x) - (y))) |
| 69 | +#define JUMP_GT(label) { if (M(test_result) > 0) goto label; } |
| 70 | +#define JUMP_LT(label) { if (M(test_result) < 0) goto label; } |
| 71 | +#define JUMP_GE(label) { if (M(test_result) >= 0) goto label; } |
| 72 | +#define JUMP_LE(label) { if (M(test_result) <= 0) goto label; } |
| 73 | +#define JUMP_EQ(label) { if (M(test_result) == 0) goto label; } |
| 74 | +#define JUMP_NE(label) { if (M(test_result) != 0) goto label; } |
| 75 | +#define JUMP(label) { goto label; } |
| 76 | +#define JUMPA(address) { goto *(void *)address; } |
| 77 | +#define PUSH(x) { M(stack)[SP++] = (x); } |
| 78 | +#define POP(x) { (x) = M(stack)[--SP]; } |
| 79 | +#define DROP(n) { SP -= (n); } |
| 80 | +#define MOV(x, y) { (x) = (y); } |
| 81 | + |
| 82 | +#define DECR(x) { --(x); } |
| 83 | +#define INCR(x) { ++(x); } |
| 84 | + |
| 85 | +#define ADD(x, y) { (x) += (y); } |
| 86 | +#define SUB(x, y) { (x) -= (y); } |
| 87 | +#define MUL(x, y) { (x) *= (y); } |
| 88 | +#define DIV(x, y) { (x) /= (y); } |
| 89 | +#define REM(x, y) { (x) %= (y); } |
| 90 | + |
| 91 | +#define SHR(x, n) { (x) >>= n; } |
| 92 | +#define SHL(x, n) { (x) <<= n; } |
| 93 | + |
| 94 | +#define AND(x, y) { (x) = (x) & (y); } |
| 95 | +#define OR(x, y) { (x) = (x) | (y); } |
| 96 | +#define XOR(x, y) { (x) ^= (y); } |
| 97 | +#define NEG(x) { (x) = ~(x); } |
| 98 | + |
| 99 | +#define BEGIN_LOCAL_LABELS { __label__ |
| 100 | +#define END_LOCAL_LABELS } |
| 101 | + |
| 102 | +#define CALL(subr) { \ |
| 103 | + __label__ Lcisc; \ |
| 104 | + M(stack)[SP++] = L(&&Lcisc); \ |
| 105 | + goto subr; \ |
| 106 | + Lcisc: ; } |
| 107 | + |
| 108 | +#define CALLA(addr) { \ |
| 109 | + __label__ Lcisc; \ |
| 110 | + M(stack)[SP++] = L(&&Lcisc); \ |
| 111 | + goto *(void *)addr; \ |
| 112 | + Lcisc: ; } |
| 113 | + |
| 114 | +#define RETURN { \ |
| 115 | + goto *(void *)M(stack)[--SP]; } |
| 116 | + |
| 117 | +#define NOP ; |
| 118 | +#define HALT { exit(0); } |
| 119 | + |
| 120 | +#define IN(x, y) { \ |
| 121 | + switch (y) { \ |
| 122 | + case 1: (x) = (long)getchar(); break; \ |
| 123 | + default: break; \ |
| 124 | + } \ |
| 125 | +} |
| 126 | + |
| 127 | +#define OUT(x, y) { \ |
| 128 | + switch (x) { \ |
| 129 | + case 2: putchar((char)(y & 255)); break; \ |
| 130 | + default: break; \ |
| 131 | + } \ |
| 132 | +} |
| 133 | + |
| 134 | +#define START_MACHINE \ |
| 135 | + Machine *machine = \ |
| 136 | + (Machine *)malloc(sizeof(Machine)); \ |
| 137 | + MOV(SP, IMM(0)); \ |
| 138 | + MOV(ADDR(0), IMM(1)) |
| 139 | + |
| 140 | +#define STOP_MACHINE \ |
| 141 | + free(machine) |
| 142 | + |
| 143 | +/* Set to 0 for no-debug, 1 for trace, 2 for step: */ |
| 144 | +/* #define DO_SHOW 0 */ |
| 145 | + |
| 146 | +/* for debugging only, use SHOW("<some message>, <arg> */ |
| 147 | +#if DO_SHOW==2 |
| 148 | +#define SHOW(msg, x) { \ |
| 149 | + printf("%s %s = %ld\n", (msg), (#x), (x)); \ |
| 150 | + getchar(); } |
| 151 | +#elif DO_SHOW==1 |
| 152 | +#define SHOW(msg, x) { printf("%s %s = %ld\n", (msg), (#x), (x)); } |
| 153 | +#else |
| 154 | +#define SHOW(msg, x) {} |
| 155 | +#endif |
0 commit comments