diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-03-31 23:10:44 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-03-31 23:10:44 +0300 |
| commit | ab276c733ce9dc80983e5c8ae5c530e1477cf990 (patch) | |
| tree | ef5da32c91d27da7a53a26e8d501f0ea616558c8 /tasm/src | |
| parent | a152fbd956cc9cb9c05a233abe004ba3d12767a0 (diff) | |
| download | tri-ab276c733ce9dc80983e5c8ae5c530e1477cf990.tar.gz tri-ab276c733ce9dc80983e5c8ae5c530e1477cf990.zip | |
implement more meta instructions
+ Also have a working draft of ABI names for registers, matches qbt
currently but should probably codify somewhere
Diffstat (limited to 'tasm/src')
| -rw-r--r-- | tasm/src/assembler.c | 43 | ||||
| -rw-r--r-- | tasm/src/lexer.l | 87 | ||||
| -rw-r--r-- | tasm/src/parser.y | 24 |
3 files changed, 136 insertions, 18 deletions
diff --git a/tasm/src/assembler.c b/tasm/src/assembler.c index 0e06a1e..896ce74 100644 --- a/tasm/src/assembler.c +++ b/tasm/src/assembler.c @@ -121,8 +121,11 @@ void emit_s(struct asm_ctx *ctx, tri_t opcode, abort(); return; } - tri_t imm4 = tri_mask(imm9, 4); - tri_t imm5 = tri_mask(tri_sr(imm9, 4), 5); + + /* low five */ + tri_t imm5 = tri_mask(imm9, 5); + /* high four */ + tri_t imm4 = tri_mask(tri_sr(imm9, 5), 4); tri_t i = build_s(opcode, imm4, fn0, xrs1, xrs2, imm5); emit(ctx, i); @@ -326,6 +329,12 @@ static void asm_ctx_destroy(struct asm_ctx *ctx) free(ctx); } +/* convert instruction index (as used by ctx->idx) to addresses */ +static size_t asm_addr(size_t o) +{ + return o * 3; +} + static void fix_reloc_la(struct asm_ctx *ctx, size_t ro, size_t so) { tri_t t = tri_from(so); @@ -354,7 +363,7 @@ static void fix_reloc_la(struct asm_ctx *ctx, size_t ro, size_t so) static void fix_reloc_b(struct asm_ctx *ctx, size_t ro, size_t so) { - int64_t off = so - ctx->idx; + int64_t off = asm_addr(so) - asm_addr(ro); tri_t t = tri_from(off); if (tri_mask(t, 9) != t) { /* should really be line based rather than offset, but good @@ -379,12 +388,6 @@ static void fix_reloc_b(struct asm_ctx *ctx, size_t ro, size_t so) ctx->buf[ro] = build_s(OPCODE_BRANCH, hi, fn0, rs1, rs2, lo); } -/* convert instruction index (as used by ctx->idx) to addresses */ -static size_t asm_addr(size_t o) -{ - return o * 3; -} - static void fix_reloc_j(struct asm_ctx *ctx, size_t ro, size_t so) { /* internal offsets are instruction indexes, so convert to address */ @@ -406,6 +409,27 @@ static void fix_reloc_j(struct asm_ctx *ctx, size_t ro, size_t so) ctx->buf[ro] = build_u(OPCODE_JAL, rd, t); } +static void fix_reloc_call(struct asm_ctx *ctx, size_t ro, size_t so) +{ + int64_t off = asm_addr(so) - asm_addr(ro); + tri_t t = tri_from(off); + + tri_t a = ctx->buf[ro]; + assert(parse_opcode(a) == OPCODE_AUIPC); + + tri_t rd, imm18; + parse_u(a, &rd, &imm18); + assert(imm18 == 0); + + ctx->buf[ro] = build_u(OPCODE_AUIPC, rd, tri_sr(t, 9)); + + tri_t j = ctx->buf[ro + 1]; + assert(parse_opcode(j) == OPCODE_JALR); + tri_t fn0, rs1, imm; + parse_i(j, &rd, &fn0, &rs1, &imm); + ctx->buf[ro + 1] = build_i(OPCODE_JALR, rd, fn0, rs1, tri_mask(t, 9)); +} + static int try_fix_reloc(struct asm_ctx *ctx, struct asm_reloc r) { /* ideally this would probably be a hashmap, but good enough for now */ @@ -421,6 +445,7 @@ static int try_fix_reloc(struct asm_ctx *ctx, struct asm_reloc r) case RELOC_LA: fix_reloc_la(ctx, ro, so); break; case RELOC_B: fix_reloc_b(ctx, ro, so); break; case RELOC_J: fix_reloc_j(ctx, ro, so); break; + case RELOC_CALL: fix_reloc_call(ctx, ro, so); break; default: fprintf(stderr, "unimplemented reloc: %d\n", r.kind); abort(); } diff --git a/tasm/src/lexer.l b/tasm/src/lexer.l index cf63cfe..a10021b 100644 --- a/tasm/src/lexer.l +++ b/tasm/src/lexer.l @@ -29,7 +29,7 @@ static void update_yylloc(struct parser *parser, YYLTYPE *lloc, const char *text %x SC_COMMENT -id [_a-zA-Z][_a-zA-Z0-9]* +id [._a-zA-Z][._a-zA-Z0-9]* label {id}[[:space:]]*: dec -?[0-9]+ @@ -149,6 +149,87 @@ str \"(\\.|[^"\\])*\" "x79" {return x79;} "x80" {return x80;} +"sp" {return x1;} +"fp" {return x2;} +"gp" {return x3;} +"a0" {return x4;} +"a1" {return x5;} +"a2" {return x6;} +"a3" {return x7;} +"a4" {return x8;} +"a5" {return x9;} +"a6" {return x10;} +"t0" {return x11;} +"t1" {return x12;} +"t2" {return x13;} +"t3" {return x14;} +"t4" {return x15;} +"t5" {return x16;} +"t6" {return x17;} +"s0" {return x18;} +"s1" {return x19;} +"s2" {return x20;} +"s3" {return x21;} +"s4" {return x22;} +"s5" {return x23;} +"s6" {return x24;} +"tp" {return x25;} +"ra" {return x26;} +"a7" {return x27;} +"a8" {return x28;} +"a9" {return x29;} +"a10" {return x30;} +"a11" {return x31;} +"a12" {return x32;} +"a13" {return x33;} +"a14" {return x34;} +"a15" {return x35;} +"a16" {return x36;} +"a17" {return x37;} +"a18" {return x38;} +"a19" {return x39;} +"a20" {return x40;} +"a21" {return x41;} +"a22" {return x42;} +"a23" {return x43;} +"a24" {return x44;} +"t7" {return x45;} +"t8" {return x46;} +"t9" {return x47;} +"t10" {return x48;} +"t11" {return x49;} +"t12" {return x50;} +"t13" {return x51;} +"t14" {return x52;} +"t15" {return x53;} +"t16" {return x54;} +"t17" {return x55;} +"t18" {return x56;} +"t19" {return x57;} +"t20" {return x58;} +"t21" {return x59;} +"t22" {return x60;} +"t23" {return x61;} +"t24" {return x62;} +"s7" {return x63;} +"s8" {return x64;} +"s9" {return x65;} +"s10" {return x66;} +"s11" {return x67;} +"s12" {return x68;} +"s13" {return x69;} +"s14" {return x70;} +"s15" {return x71;} +"s16" {return x72;} +"s17" {return x73;} +"s18" {return x74;} +"s19" {return x75;} +"s20" {return x76;} +"s21" {return x77;} +"s22" {return x78;} +"s23" {return x79;} +"s24" {return x80;} + "addi" {return addi; /* i */} "slti" {return slti;} "sgei" {return sgei;} @@ -184,6 +265,10 @@ str \"(\\.|[^"\\])*\" "mv" {return mv;} "li" {return li;} "la" {return la;} +"call" {return call;} +"ret" {return ret;} +"ble" {return ble;} +"bgt" {return bgt;} "mul" {return mul; /* m */} "div" {return diV;} diff --git a/tasm/src/parser.y b/tasm/src/parser.y index 204fe0a..bb3090f 100644 --- a/tasm/src/parser.y +++ b/tasm/src/parser.y @@ -73,7 +73,7 @@ %token ecall ebreak pcall %token fence /* meta */ -%token mv li la nop +%token mv li la nop call ret ble bgt /* m (avoid name clash with stdlib div) */ %token mul diV rem @@ -312,11 +312,11 @@ i {emit_reloc(ctx, RELOC_B, $6); emit_s(ctx, OPCODE_BRANCH, BRANCH_BGE, $2, $4, 0);} - | ld width "," gpr "," imm "(" gpr ")" - {emit_i(ctx, OPCODE_LOAD, check_width($2), $4, $8, $6);} + | ld width gpr "," imm "(" gpr ")" + {emit_i(ctx, OPCODE_LOAD, $3, check_width($2), $7, $5);} - | st width "," gpr "," imm "(" gpr ")" - {emit_s(ctx, OPCODE_STORE, check_width($2), $4, $8, $6);} + | st width gpr "," imm "(" gpr ")" + {emit_s(ctx, OPCODE_STORE, check_width($2), $3, $7, $5);} | ecall {emit_i(ctx, OPCODE_SYSTEM, X0_NUM, SYSTEM_ECALL, X0_NUM, 0);} @@ -349,10 +349,18 @@ i emit_i(ctx, OPCODE_OP_IMM, $2, OP_IMM_ADDI, $2, 0);} | li gpr "," imm - {emit_u(ctx, OPCODE_LUI, $2, tri_sr($4, 9)); + {/** @todo skip lui if we can avoid it? */ + emit_u(ctx, OPCODE_LUI, $2, tri_sr($4, 9)); emit_i(ctx, OPCODE_OP_IMM, $2, OP_IMM_ADDI, $2, tri_mask($4, 9));} - /* stuff like call and ret TBD once I've come up with a proper register - * calling convention so we know which register to use as ra */ + | call gpr "," addr + {emit_reloc(ctx, RELOC_CALL, $4); + emit_u(ctx, OPCODE_AUIPC, $2, 0); + emit_i(ctx, OPCODE_JALR, $2, 0, $2, 0);} + | ret gpr + {emit_i(ctx, OPCODE_JALR, X0_NUM, 0, $2, 0);} + | ble gpr "," gpr "," addr + {emit_reloc(ctx, RELOC_B, $6); + emit_s(ctx, OPCODE_BRANCH, BRANCH_BGE, $4, $2, 0);} m : mul gpr "," gpr "," gpr |
