tinycc-devel
[Top][All Lists]
Advanced

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

[Tinycc-devel] [PATCH 1/3] arm-asm: Implement asm_gen_code


From: Danny Milosavljevic
Subject: [Tinycc-devel] [PATCH 1/3] arm-asm: Implement asm_gen_code
Date: Sun, 3 Jan 2021 01:45:35 +0100

---
 arm-asm.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 80 insertions(+), 3 deletions(-)

diff --git a/arm-asm.c b/arm-asm.c
index 1aeb28c..d0c3de1 100644
--- a/arm-asm.c
+++ b/arm-asm.c
@@ -1214,10 +1214,87 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue 
*sv, int modifier)
 
 /* generate prolog and epilog code for asm statement */
 ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
-                         int nb_outputs, int is_output,
-                         uint8_t *clobber_regs,
-                         int out_reg)
+                          int nb_outputs, int is_output,
+                          uint8_t *clobber_regs,
+                          int out_reg)
 {
+    uint8_t regs_allocated[NB_ASM_REGS];
+    ASMOperand *op;
+    int i, reg;
+    uint32_t saved_regset = 0;
+
+    // TODO: Check non-E ABI.
+    // Note: Technically, r13 (sp) is also callee-saved--but that does not 
matter yet
+    static uint8_t reg_saved[] = { 4, 5, 6, 7, 8, 9 /* Note: sometimes special 
reg "sb" */ , 10, 11 };
+
+    /* mark all used registers */
+    memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
+    for(i = 0; i < nb_operands;i++) {
+        op = &operands[i];
+        if (op->reg >= 0)
+            regs_allocated[op->reg] = 1;
+    }
+    for(i = 0; i < sizeof(reg_saved)/sizeof(reg_saved[0]); i++) {
+        reg = reg_saved[i];
+        if (regs_allocated[reg])
+            saved_regset |= 1 << reg;
+    }
+
+    if (!is_output) { // prolog
+        /* generate reg save code */
+        if (saved_regset)
+            gen_le32(0xe92d0000 | saved_regset); // push {...}
+
+        /* generate load code */
+        for(i = 0; i < nb_operands; i++) {
+            op = &operands[i];
+            if (op->reg >= 0) {
+                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
+                    op->is_memory) {
+                    /* memory reference case (for both input and
+                       output cases) */
+                    SValue sv;
+                    sv = *op->vt;
+                    sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
+                    sv.type.t = VT_PTR;
+                    load(op->reg, &sv);
+                } else if (i >= nb_outputs || op->is_rw) { // not write-only
+                    /* load value in register */
+                    load(op->reg, op->vt);
+                    if (op->is_llong)
+                        tcc_error("long long not implemented");
+                }
+            }
+        }
+    } else { // epilog
+        /* generate save code */
+        for(i = 0 ; i < nb_outputs; i++) {
+            op = &operands[i];
+            if (op->reg >= 0) {
+                if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
+                    if (!op->is_memory) {
+                        SValue sv;
+                        sv = *op->vt;
+                        sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
+                        sv.type.t = VT_PTR;
+                        load(out_reg, &sv);
+
+                        sv = *op->vt;
+                        sv.r = (sv.r & ~VT_VALMASK) | out_reg;
+                        store(op->reg, &sv);
+                    }
+                } else {
+                    store(op->reg, op->vt);
+                    if (op->is_llong)
+                        tcc_error("long long not implemented");
+                }
+            }
+        }
+
+        /* generate reg restore code */
+        if (saved_regset)
+            gen_le32(0xe8bd0000 | saved_regset); // pop {...}
+    }
 }
 
 ST_FUNC void asm_compute_constraints(ASMOperand *operands,



reply via email to

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