summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornoneofyourbusiness <noneofyourbusiness@danwin1210.de>2023-12-10 22:36:49 +0100
committernoneofyourbusiness <noneofyourbusiness@danwin1210.de>2023-12-12 09:44:37 +0100
commitada17a08ebc9efa7ac7851d70abc803f5aeb9821 (patch)
treec7f379387c93806c78d8c3144cf68646afc5d585
parentb390feec6d4c0dfc9327ac877c7d96bb27af32fd (diff)
riscv64-asm.c: add support for calculating addresses of symbols
add some pseudoinstructions riscv64-tok.h: add pseudoinstructions from tables 25.{2,3}
-rw-r--r--riscv64-asm.c42
-rw-r--r--riscv64-tok.h46
2 files changed, 83 insertions, 5 deletions
diff --git a/riscv64-asm.c b/riscv64-asm.c
index 9c9c6b9..a83a1ac 100644
--- a/riscv64-asm.c
+++ b/riscv64-asm.c
@@ -167,6 +167,7 @@ static void asm_nullary_opcode(TCCState *s1, int token)
static void parse_operand(TCCState *s1, Operand *op)
{
ExprValue e = {0};
+ Sym label = {0};
int8_t reg;
op->type = 0;
@@ -190,6 +191,19 @@ static void parse_operand(TCCState *s1, Operand *op)
if (!op->e.sym) {
if (op->e.v < 0x1000)
op->type = OP_IM12S;
+ } else if (op->e.sym->type.t & (VT_EXTERN | VT_STATIC)) {
+ label.type.t = VT_VOID | VT_STATIC;
+
+ /* use the medium PIC model: GOT, auipc, lw */
+ if (op->e.sym->type.t & VT_STATIC)
+ greloca(cur_text_section, op->e.sym, ind, R_RISCV_PCREL_HI20, 0);
+ else
+ greloca(cur_text_section, op->e.sym, ind, R_RISCV_GOT_HI20, 0);
+ put_extern_sym(&label, cur_text_section, ind, 0);
+ greloca(cur_text_section, &label, ind+4, R_RISCV_PCREL_LO12_I, 0);
+
+ op->type = OP_IM12S;
+ op->e.v = 0;
} else {
expect("operand");
}
@@ -206,6 +220,7 @@ static void asm_unary_opcode(TCCState *s1, int token)
opcode |= ENCODE_RD(op.reg);
switch (token) {
+ /* pseudoinstructions */
case TOK_ASM_rdcycle:
asm_emit_opcode(opcode | (0xC00 << 20));
return;
@@ -224,6 +239,7 @@ static void asm_unary_opcode(TCCState *s1, int token)
case TOK_ASM_rdinstreth:
asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
return;
+ /* C extension */
case TOK_ASM_c_j:
asm_emit_cj(token, 1 | (5 << 13), &op);
return;
@@ -375,6 +391,21 @@ static void asm_binary_opcode(TCCState* s1, int token)
asm_emit_css(token, 2 | (5 << 13), ops, ops + 1);
return;
+ /* pseudoinstructions */
+ /* rd, sym */
+ case TOK_ASM_la:
+ /* auipc rd, 0 */
+ asm_emit_u(token, 3 | (5 << 2), ops, ops + 1);
+ /* lw rd, rd, 0 */
+ asm_emit_i(token, 3 | (2 << 12), ops, ops, ops + 1);
+ return;
+ case TOK_ASM_lla:
+ /* auipc rd, 0 */
+ asm_emit_u(token, 3 | (5 << 2), ops, ops + 1);
+ /* addi rd, rd, 0 */
+ asm_emit_i(token, 3 | (4 << 2), ops, ops, ops + 1);
+ return;
+
default:
expect("binary instruction");
}
@@ -807,7 +838,6 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_hrts:
case TOK_ASM_mrth:
case TOK_ASM_mrts:
- case TOK_ASM_nop:
case TOK_ASM_wfi:
asm_nullary_opcode(s1, token);
return;
@@ -952,6 +982,16 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
asm_ternary_opcode(s1, token);
return;
+ /* pseudoinstructions */
+ case TOK_ASM_nop:
+ asm_nullary_opcode(s1, token);
+ return;
+
+ case TOK_ASM_la:
+ case TOK_ASM_lla:
+ asm_binary_opcode(s1, token);
+ return;
+
default:
expect("known instruction");
}
diff --git a/riscv64-tok.h b/riscv64-tok.h
index 92369d9..ecf448e 100644
--- a/riscv64-tok.h
+++ b/riscv64-tok.h
@@ -244,10 +244,6 @@
DEF_ASM(rdinstret)
DEF_ASM(rdinstreth)
-/* no operation */
- DEF_ASM(nop)
- DEF_ASM_WITH_SUFFIX(c, nop)
-
/* “M” Standard Extension for Integer Multiplication and Division, V2.0 */
DEF_ASM(mul)
DEF_ASM(mulh)
@@ -265,6 +261,7 @@
DEF_ASM(remuw)
/* "C" Extension for Compressed Instructions, V2.0 */
+ DEF_ASM_WITH_SUFFIX(c, nop)
/* Loads */
DEF_ASM_WITH_SUFFIX(c, li)
DEF_ASM_WITH_SUFFIX(c, lw)
@@ -360,8 +357,10 @@
DEF_ASM(csrw)
DEF_ASM(csrwi)
DEF_ASM(frcsr)
+ DEF_ASM(frflags)
DEF_ASM(frrm)
DEF_ASM(fscsr)
+ DEF_ASM(fsflags)
DEF_ASM(fsrm)
/* Privileged Instructions */
@@ -371,4 +370,43 @@
DEF_ASM(hrts)
DEF_ASM(wfi)
+/* pseudoinstructions */
+ DEF_ASM(beqz)
+ DEF_ASM(bgez)
+ DEF_ASM(bgt)
+ DEF_ASM(bgtu)
+ DEF_ASM(bgtz)
+ DEF_ASM(ble)
+ DEF_ASM(bleu)
+ DEF_ASM(blez)
+ DEF_ASM(bltz)
+ DEF_ASM(bnez)
+ DEF_ASM(call)
+ DEF_ASM_WITH_SUFFIX(fabs, d)
+ DEF_ASM_WITH_SUFFIX(fabs, s)
+ DEF_ASM(fld)
+ DEF_ASM(flw)
+ DEF_ASM_WITH_SUFFIX(fmv, d)
+ DEF_ASM_WITH_SUFFIX(fmv, s)
+ DEF_ASM_WITH_SUFFIX(fneg, d)
+ DEF_ASM_WITH_SUFFIX(fneg, s)
+ DEF_ASM(fsd)
+ DEF_ASM(fsw)
+ DEF_ASM(j)
+ DEF_ASM(la)
+ DEF_ASM(li)
+ DEF_ASM(lla)
+ DEF_ASM(mv)
+ DEF_ASM(neg)
+ DEF_ASM(negw)
+ DEF_ASM(nop)
+ DEF_ASM(not)
+ DEF_ASM(ret)
+ DEF_ASM(seqz)
+ DEF_ASM_WITH_SUFFIX(sext, w)
+ DEF_ASM(sgtz)
+ DEF_ASM(sltz)
+ DEF_ASM(snez)
+ DEF_ASM(tail)
+
#undef DEF_ASM_WITH_SUFFIX