Initial commit: GKERN glyph kernel
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
#include "assembler.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *input = NULL; const char *output = "a.gobj";
|
||||
for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) output = argv[++i]; else input = argv[i]; }
|
||||
if (!input) { printf("Usage: %s <file.gasm> -o <out.gobj>\n", argv[0]); return 1; }
|
||||
Assembler as; asm_init(&as);
|
||||
if (asm_assemble(&as, input) != 0) return 1;
|
||||
if (asm_write_gobj(&as, output) != 0) return 1;
|
||||
printf("Assembled %s -> %s (%u instructions)\n", input, output, as.code_len);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "assembler.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
typedef struct { const char *mnemonic; uint8_t family_id; uint8_t sub_id; uint8_t opclass; ExtKind ext_kind; } MnemonicEntry;
|
||||
static const MnemonicEntry MNEMONICS[] = {
|
||||
{"REGION_NEW", 4, 0, 0, EXT_STORE}, {"REGION_FILL_ASC", 5, 2, 0, EXT_NONE}, {"REGION_FILL_NOISE", 5, 3, 0, EXT_NONE}, {"REGION_FILL_CONST", 5, 4, 0, EXT_NONE},
|
||||
{"ADD", 8, 0, 1, EXT_NONE}, {"HALT", 20, 0, 2, EXT_NONE}, {NULL, 0, 0, 0, EXT_NONE}
|
||||
};
|
||||
void asm_init(Assembler *as) { memset(as, 0, sizeof(Assembler)); }
|
||||
static const MnemonicEntry *lookup_mnemonic(const char *name) { for (int i = 0; MNEMONICS[i].mnemonic != NULL; i++) if (strcasecmp(name, MNEMONICS[i].mnemonic) == 0) return &MNEMONICS[i]; return NULL; }
|
||||
static int parse_operand(Assembler *as, const char *tok, uint8_t *out) {
|
||||
if (tok[0] == '%' && (tok[1] == 'r' || tok[1] == 'R')) { *out = (uint8_t)atoi(tok + 2); return 0; }
|
||||
*out = (uint8_t)(atoi(tok) & 0xFF); return 0;
|
||||
}
|
||||
static void process_line(Assembler *as, char *line) {
|
||||
char *comment = strchr(line, ';'); if (comment) *comment = '\0';
|
||||
while (*line && isspace(*line)) line++; if (*line == '\0') return;
|
||||
char *tokens[MAX_TOKENS]; int ntokens = 0; char *save;
|
||||
char *tok = strtok_r(line, " \t,\n\r", &save);
|
||||
while (tok && ntokens < MAX_TOKENS) { tokens[ntokens++] = tok; tok = strtok_r(NULL, " \t,\n\r", &save); }
|
||||
if (ntokens == 0) return;
|
||||
char mnemonic[64]; strncpy(mnemonic, tokens[0], sizeof(mnemonic) - 1); mnemonic[63] = '\0';
|
||||
const MnemonicEntry *entry = lookup_mnemonic(mnemonic);
|
||||
if (!entry) { if (as->pass == 1) fprintf(stderr, "Unknown mnemonic: %s\n", mnemonic); return; }
|
||||
uint8_t op_a = 0, op_b = 0;
|
||||
if (ntokens >= 2) parse_operand(as, tokens[1], &op_a);
|
||||
if (ntokens >= 3) parse_operand(as, tokens[2], &op_b);
|
||||
uint32_t word = glyph_encode(entry->family_id, entry->sub_id, MODE_USER, entry->opclass, glyph_encode_ops(op_a, op_b));
|
||||
if (as->pass == 1 && as->code_len < MAX_CODE_SIZE) as->code[as->code_len] = word;
|
||||
as->code_len++;
|
||||
}
|
||||
int asm_assemble(Assembler *as, const char *path) {
|
||||
as->filename = path;
|
||||
for (int pass = 0; pass <= 1; pass++) {
|
||||
as->pass = pass; if (pass == 1) as->code_len = 0;
|
||||
FILE *f = fopen(path, "r"); if (!f) return -1;
|
||||
char line[MAX_LINE]; as->line_num = 0;
|
||||
while (fgets(line, sizeof(line), f)) { as->line_num++; process_line(as, line); }
|
||||
fclose(f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int asm_write_gobj(Assembler *as, const char *path) {
|
||||
FILE *f = fopen(path, "wb"); if (!f) return -1;
|
||||
GobjHeader hdr; memcpy(hdr.magic, GOBJ_MAGIC, 8); hdr.version = GOBJ_VERSION; hdr.code_len = as->code_len; hdr.ext_len = as->ext_len;
|
||||
fwrite(&hdr, sizeof(GobjHeader), 1, f); fwrite(as->code, sizeof(uint32_t), as->code_len, f);
|
||||
fclose(f); return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef GLYPH_ASSEMBLER_H
|
||||
#define GLYPH_ASSEMBLER_H
|
||||
#include "../common/glyph_types.h"
|
||||
#include "../common/glyph_decode.h"
|
||||
#define MAX_TOKENS 8
|
||||
#define MAX_LINE 512
|
||||
#define MAX_LABELS 256
|
||||
typedef struct { char name[64]; uint32_t address; } Label;
|
||||
typedef struct { uint32_t code[MAX_CODE_SIZE]; uint32_t code_len; ExtSlot ext[MAX_EXT_SLOTS]; uint32_t ext_len; Label labels[MAX_LABELS]; uint32_t label_count; int pass; int errors; int line_num; const char *filename; } Assembler;
|
||||
void asm_init(Assembler *as);
|
||||
int asm_assemble(Assembler *as, const char *path);
|
||||
int asm_write_gobj(Assembler *as, const char *path);
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "../common/glyph_types.h"
|
||||
#include "../common/glyph_decode.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) return 1;
|
||||
FILE *f = fopen(argv[1], "rb"); if (!f) return 1;
|
||||
GobjHeader hdr; fread(&hdr, sizeof(GobjHeader), 1, f);
|
||||
uint32_t *code = malloc(hdr.code_len * sizeof(uint32_t)); fread(code, sizeof(uint32_t), hdr.code_len, f); fclose(f);
|
||||
printf("; Disassembly of %s (%u instructions)\n", argv[1], hdr.code_len);
|
||||
for (uint32_t i = 0; i < hdr.code_len; i++) {
|
||||
GlyphInstr ins = glyph_decode(code[i]);
|
||||
uint8_t op_a, op_b; glyph_decode_ops(ins.opcode_local, &op_a, &op_b);
|
||||
printf("%04u: [0x%08X] F%02u.%u %%r%u, %%r%u\n", i, code[i], ins.family_id, ins.sub_id, op_a, op_b);
|
||||
}
|
||||
free(code); return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user