[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,