Merge pull request #9 from m1el/some-refactor

Some refactor
This commit is contained in:
m1el 2024-03-13 22:06:37 +02:00 committed by GitHub
commit 81c505cd75
7 changed files with 164 additions and 70 deletions

View file

@ -55,6 +55,8 @@ const char *TYPE_STR[] = {
}; };
const size_t NARGS = sizeof(ARGS) / sizeof(ARGS[0]); const size_t NARGS = sizeof(ARGS) / sizeof(ARGS[0]);
static
ArgMeta arg_meta(char arg) { ArgMeta arg_meta(char arg) {
for (size_t ii = 0; ii < NARGS; ii += 1) { for (size_t ii = 0; ii < NARGS; ii += 1) {
ArgMeta meta = ARGS[ii]; ArgMeta meta = ARGS[ii];

View file

@ -6,6 +6,7 @@ typedef struct ByteVec_s {
size_t len; size_t len;
} ByteVec; } ByteVec;
static
AsmError ensure_push(ByteVec *vec, size_t el_size, size_t extra) { AsmError ensure_push(ByteVec *vec, size_t el_size, size_t extra) {
if (vec->len + extra < vec->len) { if (vec->len + extra < vec->len) {
return ErrOutOfMemory; return ErrOutOfMemory;

View file

@ -5,6 +5,7 @@ typedef struct InstHtNode_s {
} InstHtNode; } InstHtNode;
typedef InstHtNode *InstHt; typedef InstHtNode *InstHt;
static
uint32_t inst_hash(const char *s, size_t len) { uint32_t inst_hash(const char *s, size_t len) {
uint32_t hash = 0; uint32_t hash = 0;
uint32_t mul = 75; uint32_t mul = 75;
@ -15,6 +16,7 @@ uint32_t inst_hash(const char *s, size_t len) {
return hash; return hash;
} }
static
InstHt build_lookup(void) { InstHt build_lookup(void) {
const size_t size = 256; const size_t size = 256;
InstHt table = (InstHt)malloc(size * sizeof(InstHtNode)); InstHt table = (InstHt)malloc(size * sizeof(InstHtNode));
@ -40,6 +42,7 @@ InstHt build_lookup(void) {
return table; return table;
} }
static
size_t inst_lookup(InstHt ht, const char *s, size_t len) { size_t inst_lookup(InstHt ht, const char *s, size_t len) {
uint32_t hash = inst_hash(s, len); uint32_t hash = inst_hash(s, len);
uint8_t *node = (uint8_t *)&ht[(size_t)(hash & 0xff)]; uint8_t *node = (uint8_t *)&ht[(size_t)(hash & 0xff)];

View file

@ -21,6 +21,7 @@ SOFTWARE.
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -39,18 +40,28 @@ SOFTWARE.
// //
#include "einfo.h" #include "einfo.h"
void hd(char *data, size_t len) { // Print space-separated hex dump of each byte, 16 bytes per line.
// Can be reversed with `xxd -p -r`.
static
void hex_dump(char *data, size_t len) {
char buf[48];
const char *alphabet = "0123456789abcdef";
for (size_t ii = 0; ii < len; ii += 1) { for (size_t ii = 0; ii < len; ii += 1) {
if (ii > 0 && (ii & 15) == 0) { size_t val = (uint8_t)data[ii];
printf("\n"); size_t pos = (ii & 0x0f) * 3;
buf[pos] = alphabet[val >> 4];
buf[pos + 1] = alphabet[val & 0x0f];
buf[pos + 2] = ' ';
if (((ii & 0x0f) == 0x0f) || ii + 1 == len) {
buf[pos + 2] = '\n';
fwrite(&buf[0], 1, pos + 3, stdout);
} }
printf("%02x", (uint8_t)data[ii]);
} }
printf("\n");
} }
#define MIN_SIZE 4096 #define MIN_SIZE 4096
static
int slurp(FILE *fd, ByteVec *out) { int slurp(FILE *fd, ByteVec *out) {
ByteVec rv = {malloc(MIN_SIZE), MIN_SIZE, 0}; ByteVec rv = {malloc(MIN_SIZE), MIN_SIZE, 0};
size_t bread = 1; size_t bread = 1;
@ -98,6 +109,7 @@ typedef struct LabelVec_s {
size_t len; size_t len;
} LabelVec; } LabelVec;
static
size_t label_lookup(LabelVec *labels, char *name, size_t len) { size_t label_lookup(LabelVec *labels, char *name, size_t len) {
size_t nlabels = labels->len; size_t nlabels = labels->len;
Label *buf = labels->buf; Label *buf = labels->buf;
@ -110,10 +122,12 @@ size_t label_lookup(LabelVec *labels, char *name, size_t len) {
return INVALID; return INVALID;
} }
// safety: assumes the buffer has enough place for specified integer size. static
// `sign` is a bitset, where bit `1` indicates that value accepts a signed int, bool check_valid_int(uint64_t val, size_t size, uint8_t sign) {
// and bit `2` indicates that value accepts an unsigned int. // All 64-bit values are considered valid.
AsmError push_int_le(char *buf, uint64_t val, size_t size, uint8_t sign) { if (size == 8) {
return true;
}
// Unsigned integers must have all upper bits set to zero. To check this, // Unsigned integers must have all upper bits set to zero. To check this,
// we shift the value right by the integer size and verify it equals zero. // we shift the value right by the integer size and verify it equals zero.
int valid_uint = (val >> (size * 8)) == 0; int valid_uint = (val >> (size * 8)) == 0;
@ -142,7 +156,15 @@ AsmError push_int_le(char *buf, uint64_t val, size_t size, uint8_t sign) {
// If the value's validity doesn't match the `sign` requirements, // If the value's validity doesn't match the `sign` requirements,
// we report an overflow. // we report an overflow.
if ((validity & sign) == 0) { return (validity & sign) != 0;
}
// safety: assumes the buffer has enough place for specified integer size.
// `sign` is a bitset, where bit `1` indicates that value accepts a signed int,
// and bit `2` indicates that value accepts an unsigned int.
static
AsmError push_int_le(char *buf, uint64_t val, size_t size, uint8_t sign) {
if (!check_valid_int(val, size, sign)) {
return ErrImmediateOverflow; return ErrImmediateOverflow;
} }
@ -152,9 +174,11 @@ AsmError push_int_le(char *buf, uint64_t val, size_t size, uint8_t sign) {
buf[ii] = val & 0xff; buf[ii] = val & 0xff;
val >>= 8; val >>= 8;
} }
return ErrOk; return ErrOk;
} }
static
AsmError assemble_instr(InstHt ht, char *input, size_t len, Token *tok, AsmError assemble_instr(InstHt ht, char *input, size_t len, Token *tok,
ByteVec *rv, HoleVec *holes) { ByteVec *rv, HoleVec *holes) {
const InstDesc *inst; const InstDesc *inst;
@ -405,7 +429,7 @@ int main(int argc, char **argv) {
goto done; goto done;
} }
if (hex_out) { if (hex_out) {
hd(out.buf, out.len); hex_dump(out.buf, out.len);
} else { } else {
fwrite(out.buf, 1, out.len, stdout); fwrite(out.buf, 1, out.len, stdout);
} }

View file

@ -5,65 +5,125 @@ typedef struct InstDesc_s {
} InstDesc; } InstDesc;
const InstDesc INST[] = { const InstDesc INST[] = {
{"un", 0x00, Empty}, {"tx", 0x01, Empty}, {.opcode = 0x00, .mnemonic = "un", .type = Empty},
{"nop", 0x02, Empty}, {"add8", 0x03, RRR}, {.opcode = 0x01, .mnemonic = "tx", .type = Empty},
{"add16", 0x04, RRR}, {"add32", 0x05, RRR}, {.opcode = 0x02, .mnemonic = "nop", .type = Empty},
{"add64", 0x06, RRR}, {"sub8", 0x07, RRR}, {.opcode = 0x03, .mnemonic = "add8", .type = RRR},
{"sub16", 0x08, RRR}, {"sub32", 0x09, RRR}, {.opcode = 0x04, .mnemonic = "add16", .type = RRR},
{"sub64", 0x0A, RRR}, {"mul8", 0x0B, RRR}, {.opcode = 0x05, .mnemonic = "add32", .type = RRR},
{"mul16", 0x0C, RRR}, {"mul32", 0x0D, RRR}, {.opcode = 0x06, .mnemonic = "add64", .type = RRR},
{"mul64", 0x0E, RRR}, {"and", 0x0F, RRR}, {.opcode = 0x07, .mnemonic = "sub8", .type = RRR},
{"or", 0x10, RRR}, {"xor", 0x11, RRR}, {.opcode = 0x08, .mnemonic = "sub16", .type = RRR},
{"slu8", 0x12, RRR}, {"slu16", 0x13, RRR}, {.opcode = 0x09, .mnemonic = "sub32", .type = RRR},
{"slu32", 0x14, RRR}, {"slu64", 0x15, RRR}, {.opcode = 0x0A, .mnemonic = "sub64", .type = RRR},
{"sru8", 0x16, RRR}, {"sru16", 0x17, RRR}, {.opcode = 0x0B, .mnemonic = "mul8", .type = RRR},
{"sru32", 0x18, RRR}, {"sru64", 0x19, RRR}, {.opcode = 0x0C, .mnemonic = "mul16", .type = RRR},
{"srs8", 0x1A, RRR}, {"srs16", 0x1B, RRR}, {.opcode = 0x0D, .mnemonic = "mul32", .type = RRR},
{"srs32", 0x1C, RRR}, {"srs64", 0x1D, RRR}, {.opcode = 0x0E, .mnemonic = "mul64", .type = RRR},
{"cmpu", 0x1E, RRR}, {"cmps", 0x1F, RRR}, {.opcode = 0x0F, .mnemonic = "and", .type = RRR},
{"diru8", 0x20, RRRR}, {"diru16", 0x21, RRRR}, {.opcode = 0x10, .mnemonic = "or", .type = RRR},
{"diru32", 0x22, RRRR}, {"diru64", 0x23, RRRR}, {.opcode = 0x11, .mnemonic = "xor", .type = RRR},
{"dirs8", 0x24, RRRR}, {"dirs16", 0x25, RRRR}, {.opcode = 0x12, .mnemonic = "slu8", .type = RRR},
{"dirs32", 0x26, RRRR}, {"dirs64", 0x27, RRRR}, {.opcode = 0x13, .mnemonic = "slu16", .type = RRR},
{"neg", 0x28, RR}, {"not", 0x29, RR}, {.opcode = 0x14, .mnemonic = "slu32", .type = RRR},
{"sxt8", 0x2A, RR}, {"sxt16", 0x2B, RR}, {.opcode = 0x15, .mnemonic = "slu64", .type = RRR},
{"sxt32", 0x2C, RR}, {"addi8", 0x2D, RRx8}, {.opcode = 0x16, .mnemonic = "sru8", .type = RRR},
{"addi16", 0x2E, RRx16}, {"addi32", 0x2F, RRx32}, {.opcode = 0x17, .mnemonic = "sru16", .type = RRR},
{"addi64", 0x30, RRx64}, {"muli8", 0x31, RRx8}, {.opcode = 0x18, .mnemonic = "sru32", .type = RRR},
{"muli16", 0x32, RRx16}, {"muli32", 0x33, RRx32}, {.opcode = 0x19, .mnemonic = "sru64", .type = RRR},
{"muli64", 0x34, RRx64}, {"andi", 0x35, RRx64}, {.opcode = 0x1A, .mnemonic = "srs8", .type = RRR},
{"ori", 0x36, RRx64}, {"xori", 0x37, RRx64}, {.opcode = 0x1B, .mnemonic = "srs16", .type = RRR},
{"slui8", 0x38, RRu8}, {"slui16", 0x39, RRu8}, {.opcode = 0x1C, .mnemonic = "srs32", .type = RRR},
{"slui32", 0x3A, RRu8}, {"slui64", 0x3B, RRu8}, {.opcode = 0x1D, .mnemonic = "srs64", .type = RRR},
{"srui8", 0x3C, RRu8}, {"srui16", 0x3D, RRu8}, {.opcode = 0x1E, .mnemonic = "cmpu", .type = RRR},
{"srui32", 0x3E, RRu8}, {"srui64", 0x3F, RRu8}, {.opcode = 0x1F, .mnemonic = "cmps", .type = RRR},
{"srsi8", 0x40, RRu8}, {"srsi16", 0x41, RRu8}, {.opcode = 0x20, .mnemonic = "diru8", .type = RRRR},
{"srsi32", 0x42, RRu8}, {"srsi64", 0x43, RRu8}, {.opcode = 0x21, .mnemonic = "diru16", .type = RRRR},
{"cmpui", 0x44, RRu64}, {"cmpsi", 0x45, RRs64}, {.opcode = 0x22, .mnemonic = "diru32", .type = RRRR},
{"cp", 0x46, RR}, {"swa", 0x47, RR}, {.opcode = 0x23, .mnemonic = "diru64", .type = RRRR},
{"li8", 0x48, Rx8}, {"li16", 0x49, Rx16}, {.opcode = 0x24, .mnemonic = "dirs8", .type = RRRR},
{"li32", 0x4A, Rx32}, {"li64", 0x4B, Rx64}, {.opcode = 0x25, .mnemonic = "dirs16", .type = RRRR},
{"lra", 0x4C, RRr32}, {"ld", 0x4D, RRu64u16}, {.opcode = 0x26, .mnemonic = "dirs32", .type = RRRR},
{"st", 0x4E, RRu64u16}, {"ldr", 0x4F, RRr32u16}, {.opcode = 0x27, .mnemonic = "dirs64", .type = RRRR},
{"str", 0x50, RRr32u16}, {"bmc", 0x51, RRu16}, {.opcode = 0x28, .mnemonic = "neg", .type = RR},
{"brc", 0x52, RRu8}, {"jmp", 0x53, r32}, {.opcode = 0x29, .mnemonic = "not", .type = RR},
{"jal", 0x54, RRr32}, {"jala", 0x55, RRu64}, {.opcode = 0x2A, .mnemonic = "sxt8", .type = RR},
{"jeq", 0x56, RRr16}, {"jne", 0x57, RRr16}, {.opcode = 0x2B, .mnemonic = "sxt16", .type = RR},
{"jltu", 0x58, RRr16}, {"jgtu", 0x59, RRr16}, {.opcode = 0x2C, .mnemonic = "sxt32", .type = RR},
{"jlts", 0x5A, RRr16}, {"jgts", 0x5B, RRr16}, {.opcode = 0x2D, .mnemonic = "addi8", .type = RRx8},
{"eca", 0x5C, Empty}, {"ebp", 0x5D, Empty}, {.opcode = 0x2E, .mnemonic = "addi16", .type = RRx16},
{"fadd32", 0x5E, RRR}, {"fadd64", 0x5F, RRR}, {.opcode = 0x2F, .mnemonic = "addi32", .type = RRx32},
{"fsub32", 0x60, RRR}, {"fsub64", 0x61, RRR}, {.opcode = 0x30, .mnemonic = "addi64", .type = RRx64},
{"fmul32", 0x62, RRR}, {"fmul64", 0x63, RRR}, {.opcode = 0x31, .mnemonic = "muli8", .type = RRx8},
{"fdiv32", 0x64, RRR}, {"fdiv64", 0x65, RRR}, {.opcode = 0x32, .mnemonic = "muli16", .type = RRx16},
{"fma32", 0x66, RRRR}, {"fma64", 0x67, RRRR}, {.opcode = 0x33, .mnemonic = "muli32", .type = RRx32},
{"fcmplt32", 0x6A, RRR}, {"fcmplt64", 0x6B, RRR}, {.opcode = 0x34, .mnemonic = "muli64", .type = RRx64},
{"fcmpgt32", 0x6C, RRR}, {"fcmpgt64", 0x6D, RRR}, {.opcode = 0x35, .mnemonic = "andi", .type = RRx64},
{"itf32", 0x6E, RR}, {"itf64", 0x6F, RR}, {.opcode = 0x36, .mnemonic = "ori", .type = RRx64},
{"fti32", 0x70, RRu8}, {"fti64", 0x71, RRu8}, {.opcode = 0x37, .mnemonic = "xori", .type = RRx64},
{"fc32t64", 0x72, RR}, {"fc64t32", 0x73, RR}, {.opcode = 0x38, .mnemonic = "slui8", .type = RRu8},
{"lra16", 0x74, RRr16}, {"ldr16", 0x75, RRr16u16}, {.opcode = 0x39, .mnemonic = "slui16", .type = RRu8},
{"str16", 0x76, RRr16u16}, {"jmp16", 0x77, r16}, {.opcode = 0x3A, .mnemonic = "slui32", .type = RRu8},
{.opcode = 0x3B, .mnemonic = "slui64", .type = RRu8},
{.opcode = 0x3C, .mnemonic = "srui8", .type = RRu8},
{.opcode = 0x3D, .mnemonic = "srui16", .type = RRu8},
{.opcode = 0x3E, .mnemonic = "srui32", .type = RRu8},
{.opcode = 0x3F, .mnemonic = "srui64", .type = RRu8},
{.opcode = 0x40, .mnemonic = "srsi8", .type = RRu8},
{.opcode = 0x41, .mnemonic = "srsi16", .type = RRu8},
{.opcode = 0x42, .mnemonic = "srsi32", .type = RRu8},
{.opcode = 0x43, .mnemonic = "srsi64", .type = RRu8},
{.opcode = 0x44, .mnemonic = "cmpui", .type = RRu64},
{.opcode = 0x45, .mnemonic = "cmpsi", .type = RRs64},
{.opcode = 0x46, .mnemonic = "cp", .type = RR},
{.opcode = 0x47, .mnemonic = "swa", .type = RR},
{.opcode = 0x48, .mnemonic = "li8", .type = Rx8},
{.opcode = 0x49, .mnemonic = "li16", .type = Rx16},
{.opcode = 0x4A, .mnemonic = "li32", .type = Rx32},
{.opcode = 0x4B, .mnemonic = "li64", .type = Rx64},
{.opcode = 0x4C, .mnemonic = "lra", .type = RRr32},
{.opcode = 0x4D, .mnemonic = "ld", .type = RRu64u16},
{.opcode = 0x4E, .mnemonic = "st", .type = RRu64u16},
{.opcode = 0x4F, .mnemonic = "ldr", .type = RRr32u16},
{.opcode = 0x50, .mnemonic = "str", .type = RRr32u16},
{.opcode = 0x51, .mnemonic = "bmc", .type = RRu16},
{.opcode = 0x52, .mnemonic = "brc", .type = RRu8},
{.opcode = 0x53, .mnemonic = "jmp", .type = r32},
{.opcode = 0x54, .mnemonic = "jal", .type = RRr32},
{.opcode = 0x55, .mnemonic = "jala", .type = RRu64},
{.opcode = 0x56, .mnemonic = "jeq", .type = RRr16},
{.opcode = 0x57, .mnemonic = "jne", .type = RRr16},
{.opcode = 0x58, .mnemonic = "jltu", .type = RRr16},
{.opcode = 0x59, .mnemonic = "jgtu", .type = RRr16},
{.opcode = 0x5A, .mnemonic = "jlts", .type = RRr16},
{.opcode = 0x5B, .mnemonic = "jgts", .type = RRr16},
{.opcode = 0x5C, .mnemonic = "eca", .type = Empty},
{.opcode = 0x5D, .mnemonic = "ebp", .type = Empty},
{.opcode = 0x5E, .mnemonic = "fadd32", .type = RRR},
{.opcode = 0x5F, .mnemonic = "fadd64", .type = RRR},
{.opcode = 0x60, .mnemonic = "fsub32", .type = RRR},
{.opcode = 0x61, .mnemonic = "fsub64", .type = RRR},
{.opcode = 0x62, .mnemonic = "fmul32", .type = RRR},
{.opcode = 0x63, .mnemonic = "fmul64", .type = RRR},
{.opcode = 0x64, .mnemonic = "fdiv32", .type = RRR},
{.opcode = 0x65, .mnemonic = "fdiv64", .type = RRR},
{.opcode = 0x66, .mnemonic = "fma32", .type = RRRR},
{.opcode = 0x67, .mnemonic = "fma64", .type = RRRR},
// 68, 69?
{.opcode = 0x6A, .mnemonic = "fcmplt32", .type = RRR},
{.opcode = 0x6B, .mnemonic = "fcmplt64", .type = RRR},
{.opcode = 0x6C, .mnemonic = "fcmpgt32", .type = RRR},
{.opcode = 0x6D, .mnemonic = "fcmpgt64", .type = RRR},
{.opcode = 0x6E, .mnemonic = "itf32", .type = RR},
{.opcode = 0x6F, .mnemonic = "itf64", .type = RR},
{.opcode = 0x70, .mnemonic = "fti32", .type = RRu8},
{.opcode = 0x71, .mnemonic = "fti64", .type = RRu8},
{.opcode = 0x72, .mnemonic = "fc32t64", .type = RR},
{.opcode = 0x73, .mnemonic = "fc64t32", .type = RR},
{.opcode = 0x74, .mnemonic = "lra16", .type = RRr16},
{.opcode = 0x75, .mnemonic = "ldr16", .type = RRr16u16},
{.opcode = 0x76, .mnemonic = "str16", .type = RRr16u16},
{.opcode = 0x77, .mnemonic = "jmp16", .type = r16},
}; };
const size_t INST_CNT = sizeof(INST) / sizeof(INST[0]); const size_t INST_CNT = sizeof(INST) / sizeof(INST[0]);

View file

@ -1,3 +1,4 @@
static
int parse_register(char *name, size_t len) { int parse_register(char *name, size_t len) {
if (name[0] != 'r') { if (name[0] != 'r') {
return 256; // Register name should start with 'r' return 256; // Register name should start with 'r'

View file

@ -18,6 +18,7 @@ typedef struct Token_s {
uint64_t num; uint64_t num;
} Token; } Token;
static
Token token_ident(char *input, size_t len, size_t pos) { Token token_ident(char *input, size_t len, size_t pos) {
size_t start = pos; size_t start = pos;
while (pos < len) { while (pos < len) {
@ -33,6 +34,7 @@ Token token_ident(char *input, size_t len, size_t pos) {
return (Token){TokIdent, start, pos - start, 0}; return (Token){TokIdent, start, pos - start, 0};
} }
static
Token token_number(char *input, size_t len, size_t pos) { Token token_number(char *input, size_t len, size_t pos) {
char *ptr = &input[pos]; char *ptr = &input[pos];
char next = '\0'; char next = '\0';
@ -109,6 +111,7 @@ Token token_number(char *input, size_t len, size_t pos) {
} }
} }
static
Token token(char *input, size_t len, size_t pos) { Token token(char *input, size_t len, size_t pos) {
char chr, chru; char chr, chru;
char *ptr = &input[pos]; char *ptr = &input[pos];