tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] [PATCH 03/11] riscv64-asm: Add rdcycle, rdcycleh, rdtime,


From: Danny Milosavljevic
Subject: [Tinycc-devel] [PATCH 03/11] riscv64-asm: Add rdcycle, rdcycleh, rdtime, rdtimeh, rdinstret, rdinstreth
Date: Wed, 7 Apr 2021 13:53:06 +0200

---
 riscv64-asm.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++
 riscv64-tok.h |  9 +++++
 2 files changed, 103 insertions(+)

diff --git a/riscv64-asm.c b/riscv64-asm.c
index 167d525..4a1ab1d 100644
--- a/riscv64-asm.c
+++ b/riscv64-asm.c
@@ -94,6 +94,91 @@ static void asm_nullary_opcode(TCCState *s1, int token)
     }
 }
 
+enum {
+    OPT_REG,
+    OPT_IM12S,
+    OPT_IM32,
+};
+#define OP_REG    (1 << OPT_REG)
+#define OP_IM32   (1 << OPT_IM32)
+#define OP_IM12S   (1 << OPT_IM12S)
+
+typedef struct Operand {
+    uint32_t type;
+    union {
+        uint8_t reg;
+        uint16_t regset;
+        ExprValue e;
+    };
+} Operand;
+
+/* Parse a text containing operand and store the result in OP */
+static void parse_operand(TCCState *s1, Operand *op)
+{
+    ExprValue e;
+    int8_t reg;
+
+    op->type = 0;
+
+    if ((reg = asm_parse_regvar(tok)) != -1) {
+        next(); // skip register name
+        op->type = OP_REG;
+        op->reg = (uint8_t) reg;
+        return;
+    } else if (tok == '$') {
+        /* constant value */
+        next(); // skip '#' or '$'
+    }
+    asm_expr(s1, &e);
+    op->type = OP_IM32;
+    op->e = e;
+    if (!op->e.sym) {
+        if ((int) op->e.v >= -2048 && (int) op->e.v < 2048)
+            op->type = OP_IM12S;
+    } else
+        expect("operand");
+}
+
+#define ENCODE_RS1(register_index) ((register_index) << 15)
+#define ENCODE_RS2(register_index) ((register_index) << 20)
+#define ENCODE_RD(register_index) ((register_index) << 7)
+
+// Note: Those all map to CSR--so they are pseudo-instructions.
+static void asm_unary_opcode(TCCState *s1, int token)
+{
+    uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
+    Operand op;
+    parse_operand(s1, &op);
+    if (op.type != OP_REG) {
+        expect("register");
+        return;
+    }
+    opcode |= ENCODE_RD(op.reg);
+
+    switch (token) {
+    case TOK_ASM_rdcycle:
+        asm_emit_opcode(opcode | (0xC00 << 20));
+        return;
+    case TOK_ASM_rdcycleh:
+        asm_emit_opcode(opcode | (0xC80 << 20));
+        return;
+    case TOK_ASM_rdtime:
+        asm_emit_opcode(opcode | (0xC01 << 20) | ENCODE_RD(op.reg));
+        return;
+    case TOK_ASM_rdtimeh:
+        asm_emit_opcode(opcode | (0xC81 << 20) | ENCODE_RD(op.reg));
+        return;
+    case TOK_ASM_rdinstret:
+        asm_emit_opcode(opcode | (0xC02 << 20) | ENCODE_RD(op.reg));
+        return;
+    case TOK_ASM_rdinstreth:
+        asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
+        return;
+    default:
+        expect("unary instruction");
+    }
+}
+
 ST_FUNC void asm_opcode(TCCState *s1, int token)
 {
     switch (token) {
@@ -110,6 +195,15 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
         asm_nullary_opcode(s1, token);
         return;
 
+    case TOK_ASM_rdcycle:
+    case TOK_ASM_rdcycleh:
+    case TOK_ASM_rdtime:
+    case TOK_ASM_rdtimeh:
+    case TOK_ASM_rdinstret:
+    case TOK_ASM_rdinstreth:
+        asm_unary_opcode(s1, token);
+        return;
+
     default:
         expect("known instruction");
     }
diff --git a/riscv64-tok.h b/riscv64-tok.h
index af0e186..d6709ef 100644
--- a/riscv64-tok.h
+++ b/riscv64-tok.h
@@ -92,6 +92,15 @@
  DEF_ASM(scall)
  DEF_ASM(sbreak)
 
+/* Counters */
+
+ DEF_ASM(rdcycle)
+ DEF_ASM(rdcycleh)
+ DEF_ASM(rdtime)
+ DEF_ASM(rdtimeh)
+ DEF_ASM(rdinstret)
+ DEF_ASM(rdinstreth)
+
 /* Privileged Instructions */
 
  DEF_ASM(ecall)
-- 
2.29.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]