#include #include #include #include uint8_t *mem8; uint16_t *mem16; uint32_t *mem32; uint32_t R[32]; uint16_t PC = 0x2000; bool running = true; int main(int argc, char **argv) { const char *bin_name; FILE *bin; size_t binsize; mem32 = mem16 = mem8 = malloc(1024 * 1024); if (mem == NULL) { fprintf(stderr, "Error allocating memory\n"); exit(EXIT_FAILURE); } if (argc == 1) bin_name = "boot.cro"; else if (argc == 2) bin_name = argv[1]; bin = fopen(bin_name, "r"); if (bin == NULL) { fprintf(stderr, "Error opening \"%s\"\n", bin_name); exit(EXIT_FAILURE); } binsize = fread(mem + 0x8000, sizeof(uint8_t), 1024 * 1024 - 0x8000, bin); if (ferror(bin) != 0) { fprintf(stderr, "Error loading \"%s\" (ferror %d)\n", bin_name, ferror(bin)); exit(EXIT_FAILURE); } fclose(bin); while (running) { uint32_t instr = mem32[pc]; uint8_t O = instr >> 26; uint16_t I = instr & 0xFFFF; uint32_t V = instr & 0x03FFFFFF; uint8_t X = instr >> 21 & 0x3F; uint8_t Y = instr >> 16 & 0x3F; uint8_t D = instr >> 11 & 0x3F; uint8_t S = instr >> 6 & 0x3F; uint8_t F = instr & 0x3F; switch (O) { case 0x00: switch (F) { case 0x00: // NOP break; case 0x01: // HALT running = false; break; case 0x02: // PRINT fprintf(({stdout, stderr})[R[D]], "%c", (char) R[X]); break; case 0x04: // SLL R[D] = R[X] << R[Y]; break; case 0x07: // SRA if (R[X] < 0 && R[Y] % 8 > 0) { R[D] = R[X] >> R[Y] % 8 | ~(~0U >> R[Y] % 8); } else { case 0x06: // SRL (and sometimes SRA), filthy hack R[D] = R[X] >> R[Y] % 8; } break; case 0x20: // ADD R[D] = R[X] + R[Y]; break; case 0x22: // SUB R[D] = R[X] - R[Y]; break; case 0x24: // AND R[D] = R[X] & R[Y]; break; case 0x25: // OR R[D] = R[X] | R[Y]; break; case 0x26: // XOR R[D] = R[X] ^ R[Y]; break; case 0x28: // SEQ R[D] = R[X] == R[Y] ? 1 : 0; break; case 0x28: // SNE R[D] = R[X] != R[Y] ? 1 : 0; break; case 0x2A: // SLT R[D] = R[X] < R[Y] ? 1 : 0; break; case 0x2C: // SLE R[D] = R[X] <= R[Y] ? 1 : 0; break; } break; case 0x02: // J PC += V; break; case 0x03: // JAL R[31] = PC + 1; PC += V; break; case 0x04: // BEZ if (R[X] == 0) PC += I; break; case 0x05: // BNEZ if (R[X] != 0) PC += I; break; case 0x08: // ADDI R[Y] = R[X] + I; break; case 0x0A: // SUBI R[Y] = R[X] - I; break; case 0x0C: // ANDI R[Y] = R[X] & I; break; case 0x0D: // ORI R[Y] = R[X] | I; break; case 0x0E: // XORI R[Y] = R[X] ^ I; break; case 0x0F: // LHI R[Y] = I << 16; break; case 0x12: // JR CP = R[X]; break; case 0x13: // JALR R[31] = CP + 1; CP = (R[X] - R[X] % 4) / 4; break; case 0x14: // SLLI R[Y] = R[X] << I % 8; break; case 0x17: // SRAI if (R[X] < 0 && I % 8 > 0) { R[Y] = R[X] >> I % 8 | ~(~0U >> I % 8); } else { case 0x15: // SRLI (and sometimes SRAI), filthy hack R[Y] = R[X] >> I % 8; } break; case 0x18: // SEQI R[Y] = R[X] == I ? 1 : 0; break; case 0x19: // SNEI R[Y] = R[X] != I ? 1 : 0; break; case 0x1A: // SLTI R[Y] = R[X] < I ? 1 : 0; break; case 0x1C: // SLEI R[Y] = R[X] <= I ? 1 : 0; break; case 0x23: // LW R[Y] = mem32[R[X] + I]; break; case 0x23: // SW mem32[R[X] + I] = R[Y]; break; } } }