aboutsummaryrefslogtreecommitdiff
path: root/tasm/src
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-03-31 23:10:44 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-03-31 23:10:44 +0300
commitab276c733ce9dc80983e5c8ae5c530e1477cf990 (patch)
treeef5da32c91d27da7a53a26e8d501f0ea616558c8 /tasm/src
parenta152fbd956cc9cb9c05a233abe004ba3d12767a0 (diff)
downloadtri-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.c43
-rw-r--r--tasm/src/lexer.l87
-rw-r--r--tasm/src/parser.y24
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