diff --git a/src/args.c b/src/args.c index be74e1e..7837ba6 100644 --- a/src/args.c +++ b/src/args.c @@ -55,6 +55,8 @@ const char *TYPE_STR[] = { }; const size_t NARGS = sizeof(ARGS) / sizeof(ARGS[0]); + +static ArgMeta arg_meta(char arg) { for (size_t ii = 0; ii < NARGS; ii += 1) { ArgMeta meta = ARGS[ii]; diff --git a/src/bytevec.c b/src/bytevec.c index 0d87620..2002b76 100644 --- a/src/bytevec.c +++ b/src/bytevec.c @@ -6,6 +6,7 @@ typedef struct ByteVec_s { size_t len; } ByteVec; +static AsmError ensure_push(ByteVec *vec, size_t el_size, size_t extra) { if (vec->len + extra < vec->len) { return ErrOutOfMemory; diff --git a/src/hash.c b/src/hash.c index 21d1d0f..f136cdc 100644 --- a/src/hash.c +++ b/src/hash.c @@ -5,6 +5,7 @@ typedef struct InstHtNode_s { } InstHtNode; typedef InstHtNode *InstHt; +static uint32_t inst_hash(const char *s, size_t len) { uint32_t hash = 0; uint32_t mul = 75; @@ -15,6 +16,7 @@ uint32_t inst_hash(const char *s, size_t len) { return hash; } +static InstHt build_lookup(void) { const size_t size = 256; InstHt table = (InstHt)malloc(size * sizeof(InstHtNode)); @@ -40,6 +42,7 @@ InstHt build_lookup(void) { return table; } +static size_t inst_lookup(InstHt ht, const char *s, size_t len) { uint32_t hash = inst_hash(s, len); uint8_t *node = (uint8_t *)&ht[(size_t)(hash & 0xff)]; diff --git a/src/hbas.c b/src/hbas.c index 7c08e11..038419d 100644 --- a/src/hbas.c +++ b/src/hbas.c @@ -21,6 +21,7 @@ SOFTWARE. */ #include +#include #include #include #include @@ -39,18 +40,28 @@ SOFTWARE. // #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) { - if (ii > 0 && (ii & 15) == 0) { - printf("\n"); + size_t val = (uint8_t)data[ii]; + 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 +static int slurp(FILE *fd, ByteVec *out) { ByteVec rv = {malloc(MIN_SIZE), MIN_SIZE, 0}; size_t bread = 1; @@ -98,6 +109,7 @@ typedef struct LabelVec_s { size_t len; } LabelVec; +static size_t label_lookup(LabelVec *labels, char *name, size_t len) { size_t nlabels = labels->len; Label *buf = labels->buf; @@ -110,10 +122,12 @@ size_t label_lookup(LabelVec *labels, char *name, size_t len) { return INVALID; } -// 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. -AsmError push_int_le(char *buf, uint64_t val, size_t size, uint8_t sign) { +static +bool check_valid_int(uint64_t val, size_t size, uint8_t sign) { + // All 64-bit values are considered valid. + if (size == 8) { + return true; + } // 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. 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, // 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; } @@ -152,9 +174,11 @@ AsmError push_int_le(char *buf, uint64_t val, size_t size, uint8_t sign) { buf[ii] = val & 0xff; val >>= 8; } + return ErrOk; } +static AsmError assemble_instr(InstHt ht, char *input, size_t len, Token *tok, ByteVec *rv, HoleVec *holes) { const InstDesc *inst; @@ -405,7 +429,7 @@ int main(int argc, char **argv) { goto done; } if (hex_out) { - hd(out.buf, out.len); + hex_dump(out.buf, out.len); } else { fwrite(out.buf, 1, out.len, stdout); } diff --git a/src/instructions.c b/src/instructions.c index 1af9d08..17d66dc 100644 --- a/src/instructions.c +++ b/src/instructions.c @@ -5,65 +5,125 @@ typedef struct InstDesc_s { } InstDesc; const InstDesc INST[] = { - {"un", 0x00, Empty}, {"tx", 0x01, Empty}, - {"nop", 0x02, Empty}, {"add8", 0x03, RRR}, - {"add16", 0x04, RRR}, {"add32", 0x05, RRR}, - {"add64", 0x06, RRR}, {"sub8", 0x07, RRR}, - {"sub16", 0x08, RRR}, {"sub32", 0x09, RRR}, - {"sub64", 0x0A, RRR}, {"mul8", 0x0B, RRR}, - {"mul16", 0x0C, RRR}, {"mul32", 0x0D, RRR}, - {"mul64", 0x0E, RRR}, {"and", 0x0F, RRR}, - {"or", 0x10, RRR}, {"xor", 0x11, RRR}, - {"slu8", 0x12, RRR}, {"slu16", 0x13, RRR}, - {"slu32", 0x14, RRR}, {"slu64", 0x15, RRR}, - {"sru8", 0x16, RRR}, {"sru16", 0x17, RRR}, - {"sru32", 0x18, RRR}, {"sru64", 0x19, RRR}, - {"srs8", 0x1A, RRR}, {"srs16", 0x1B, RRR}, - {"srs32", 0x1C, RRR}, {"srs64", 0x1D, RRR}, - {"cmpu", 0x1E, RRR}, {"cmps", 0x1F, RRR}, - {"diru8", 0x20, RRRR}, {"diru16", 0x21, RRRR}, - {"diru32", 0x22, RRRR}, {"diru64", 0x23, RRRR}, - {"dirs8", 0x24, RRRR}, {"dirs16", 0x25, RRRR}, - {"dirs32", 0x26, RRRR}, {"dirs64", 0x27, RRRR}, - {"neg", 0x28, RR}, {"not", 0x29, RR}, - {"sxt8", 0x2A, RR}, {"sxt16", 0x2B, RR}, - {"sxt32", 0x2C, RR}, {"addi8", 0x2D, RRx8}, - {"addi16", 0x2E, RRx16}, {"addi32", 0x2F, RRx32}, - {"addi64", 0x30, RRx64}, {"muli8", 0x31, RRx8}, - {"muli16", 0x32, RRx16}, {"muli32", 0x33, RRx32}, - {"muli64", 0x34, RRx64}, {"andi", 0x35, RRx64}, - {"ori", 0x36, RRx64}, {"xori", 0x37, RRx64}, - {"slui8", 0x38, RRu8}, {"slui16", 0x39, RRu8}, - {"slui32", 0x3A, RRu8}, {"slui64", 0x3B, RRu8}, - {"srui8", 0x3C, RRu8}, {"srui16", 0x3D, RRu8}, - {"srui32", 0x3E, RRu8}, {"srui64", 0x3F, RRu8}, - {"srsi8", 0x40, RRu8}, {"srsi16", 0x41, RRu8}, - {"srsi32", 0x42, RRu8}, {"srsi64", 0x43, RRu8}, - {"cmpui", 0x44, RRu64}, {"cmpsi", 0x45, RRs64}, - {"cp", 0x46, RR}, {"swa", 0x47, RR}, - {"li8", 0x48, Rx8}, {"li16", 0x49, Rx16}, - {"li32", 0x4A, Rx32}, {"li64", 0x4B, Rx64}, - {"lra", 0x4C, RRr32}, {"ld", 0x4D, RRu64u16}, - {"st", 0x4E, RRu64u16}, {"ldr", 0x4F, RRr32u16}, - {"str", 0x50, RRr32u16}, {"bmc", 0x51, RRu16}, - {"brc", 0x52, RRu8}, {"jmp", 0x53, r32}, - {"jal", 0x54, RRr32}, {"jala", 0x55, RRu64}, - {"jeq", 0x56, RRr16}, {"jne", 0x57, RRr16}, - {"jltu", 0x58, RRr16}, {"jgtu", 0x59, RRr16}, - {"jlts", 0x5A, RRr16}, {"jgts", 0x5B, RRr16}, - {"eca", 0x5C, Empty}, {"ebp", 0x5D, Empty}, - {"fadd32", 0x5E, RRR}, {"fadd64", 0x5F, RRR}, - {"fsub32", 0x60, RRR}, {"fsub64", 0x61, RRR}, - {"fmul32", 0x62, RRR}, {"fmul64", 0x63, RRR}, - {"fdiv32", 0x64, RRR}, {"fdiv64", 0x65, RRR}, - {"fma32", 0x66, RRRR}, {"fma64", 0x67, RRRR}, - {"fcmplt32", 0x6A, RRR}, {"fcmplt64", 0x6B, RRR}, - {"fcmpgt32", 0x6C, RRR}, {"fcmpgt64", 0x6D, RRR}, - {"itf32", 0x6E, RR}, {"itf64", 0x6F, RR}, - {"fti32", 0x70, RRu8}, {"fti64", 0x71, RRu8}, - {"fc32t64", 0x72, RR}, {"fc64t32", 0x73, RR}, - {"lra16", 0x74, RRr16}, {"ldr16", 0x75, RRr16u16}, - {"str16", 0x76, RRr16u16}, {"jmp16", 0x77, r16}, + {.opcode = 0x00, .mnemonic = "un", .type = Empty}, + {.opcode = 0x01, .mnemonic = "tx", .type = Empty}, + {.opcode = 0x02, .mnemonic = "nop", .type = Empty}, + {.opcode = 0x03, .mnemonic = "add8", .type = RRR}, + {.opcode = 0x04, .mnemonic = "add16", .type = RRR}, + {.opcode = 0x05, .mnemonic = "add32", .type = RRR}, + {.opcode = 0x06, .mnemonic = "add64", .type = RRR}, + {.opcode = 0x07, .mnemonic = "sub8", .type = RRR}, + {.opcode = 0x08, .mnemonic = "sub16", .type = RRR}, + {.opcode = 0x09, .mnemonic = "sub32", .type = RRR}, + {.opcode = 0x0A, .mnemonic = "sub64", .type = RRR}, + {.opcode = 0x0B, .mnemonic = "mul8", .type = RRR}, + {.opcode = 0x0C, .mnemonic = "mul16", .type = RRR}, + {.opcode = 0x0D, .mnemonic = "mul32", .type = RRR}, + {.opcode = 0x0E, .mnemonic = "mul64", .type = RRR}, + {.opcode = 0x0F, .mnemonic = "and", .type = RRR}, + {.opcode = 0x10, .mnemonic = "or", .type = RRR}, + {.opcode = 0x11, .mnemonic = "xor", .type = RRR}, + {.opcode = 0x12, .mnemonic = "slu8", .type = RRR}, + {.opcode = 0x13, .mnemonic = "slu16", .type = RRR}, + {.opcode = 0x14, .mnemonic = "slu32", .type = RRR}, + {.opcode = 0x15, .mnemonic = "slu64", .type = RRR}, + {.opcode = 0x16, .mnemonic = "sru8", .type = RRR}, + {.opcode = 0x17, .mnemonic = "sru16", .type = RRR}, + {.opcode = 0x18, .mnemonic = "sru32", .type = RRR}, + {.opcode = 0x19, .mnemonic = "sru64", .type = RRR}, + {.opcode = 0x1A, .mnemonic = "srs8", .type = RRR}, + {.opcode = 0x1B, .mnemonic = "srs16", .type = RRR}, + {.opcode = 0x1C, .mnemonic = "srs32", .type = RRR}, + {.opcode = 0x1D, .mnemonic = "srs64", .type = RRR}, + {.opcode = 0x1E, .mnemonic = "cmpu", .type = RRR}, + {.opcode = 0x1F, .mnemonic = "cmps", .type = RRR}, + {.opcode = 0x20, .mnemonic = "diru8", .type = RRRR}, + {.opcode = 0x21, .mnemonic = "diru16", .type = RRRR}, + {.opcode = 0x22, .mnemonic = "diru32", .type = RRRR}, + {.opcode = 0x23, .mnemonic = "diru64", .type = RRRR}, + {.opcode = 0x24, .mnemonic = "dirs8", .type = RRRR}, + {.opcode = 0x25, .mnemonic = "dirs16", .type = RRRR}, + {.opcode = 0x26, .mnemonic = "dirs32", .type = RRRR}, + {.opcode = 0x27, .mnemonic = "dirs64", .type = RRRR}, + {.opcode = 0x28, .mnemonic = "neg", .type = RR}, + {.opcode = 0x29, .mnemonic = "not", .type = RR}, + {.opcode = 0x2A, .mnemonic = "sxt8", .type = RR}, + {.opcode = 0x2B, .mnemonic = "sxt16", .type = RR}, + {.opcode = 0x2C, .mnemonic = "sxt32", .type = RR}, + {.opcode = 0x2D, .mnemonic = "addi8", .type = RRx8}, + {.opcode = 0x2E, .mnemonic = "addi16", .type = RRx16}, + {.opcode = 0x2F, .mnemonic = "addi32", .type = RRx32}, + {.opcode = 0x30, .mnemonic = "addi64", .type = RRx64}, + {.opcode = 0x31, .mnemonic = "muli8", .type = RRx8}, + {.opcode = 0x32, .mnemonic = "muli16", .type = RRx16}, + {.opcode = 0x33, .mnemonic = "muli32", .type = RRx32}, + {.opcode = 0x34, .mnemonic = "muli64", .type = RRx64}, + {.opcode = 0x35, .mnemonic = "andi", .type = RRx64}, + {.opcode = 0x36, .mnemonic = "ori", .type = RRx64}, + {.opcode = 0x37, .mnemonic = "xori", .type = RRx64}, + {.opcode = 0x38, .mnemonic = "slui8", .type = RRu8}, + {.opcode = 0x39, .mnemonic = "slui16", .type = RRu8}, + {.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]); diff --git a/src/register.c b/src/register.c index b393d8b..9b2cd69 100644 --- a/src/register.c +++ b/src/register.c @@ -1,3 +1,4 @@ +static int parse_register(char *name, size_t len) { if (name[0] != 'r') { return 256; // Register name should start with 'r' diff --git a/src/token.c b/src/token.c index c8bf3ae..8612073 100644 --- a/src/token.c +++ b/src/token.c @@ -18,6 +18,7 @@ typedef struct Token_s { uint64_t num; } Token; +static Token token_ident(char *input, size_t len, size_t pos) { size_t start = pos; 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}; } +static Token token_number(char *input, size_t len, size_t pos) { char *ptr = &input[pos]; 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) { char chr, chru; char *ptr = &input[pos];