aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arm64-gen.c48
-rw-r--r--lib/lib-arm64.c2
-rw-r--r--tcc.h1
-rw-r--r--tccgen.c12
-rw-r--r--tcctok.h1
5 files changed, 63 insertions, 1 deletions
diff --git a/arm64-gen.c b/arm64-gen.c
index fe1a634..3581e5d 100644
--- a/arm64-gen.c
+++ b/arm64-gen.c
@@ -1771,6 +1771,54 @@ ST_FUNC void ggoto(void)
--vtop;
}
+ST_FUNC void gen_clear_cache(void)
+{
+ uint32_t beg, end, dsz, isz, p, lab1, b1;
+ gv2(RC_INT, RC_INT);
+ vpushi(0);
+ vtop->r = get_reg(RC_INT);
+ vpushi(0);
+ vtop->r = get_reg(RC_INT);
+ vpushi(0);
+ vtop->r = get_reg(RC_INT);
+ beg = intr(vtop[-4].r); // x0
+ end = intr(vtop[-3].r); // x1
+ dsz = intr(vtop[-2].r); // x2
+ isz = intr(vtop[-1].r); // x3
+ p = intr(vtop[0].r); // x4
+ vtop -= 5;
+
+ o(0xd53b0020 | isz); // mrs x(isz),ctr_el0
+ o(0x52800080 | p); // mov w(p),#4
+ o(0x53104c00 | dsz | isz << 5); // ubfx w(dsz),w(isz),#16,#4
+ o(0x1ac02000 | dsz | p << 5 | dsz << 16); // lsl w(dsz),w(p),w(dsz)
+ o(0x12000c00 | isz | isz << 5); // and w(isz),w(isz),#15
+ o(0x1ac02000 | isz | p << 5 | isz << 16); // lsl w(isz),w(p),w(isz)
+ o(0x51000400 | p | dsz << 5); // sub w(p),w(dsz),#1
+ o(0x8a240004 | p | beg << 5 | p << 16); // bic x(p),x(beg),x(p)
+ b1 = ind; o(0x14000000); // b
+ lab1 = ind;
+ o(0xd50b7b20 | p); // dc cvau,x(p)
+ o(0x8b000000 | p | p << 5 | dsz << 16); // add x(p),x(p),x(dsz)
+ *(uint32_t *)(cur_text_section->data + b1) =
+ (0x14000000 | (ind - b1) >> 2);
+ o(0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end)
+ o(0x54ffffa3 | ((lab1 - ind) << 3 & 0xffffe0)); // b.cc lab1
+ o(0xd5033b9f); // dsb ish
+ o(0x51000400 | p | isz << 5); // sub w(p),w(isz),#1
+ o(0x8a240004 | p | beg << 5 | p << 16); // bic x(p),x(beg),x(p)
+ b1 = ind; o(0x14000000); // b
+ lab1 = ind;
+ o(0xd50b7520 | p); // ic ivau,x(p)
+ o(0x8b000000 | p | p << 5 | isz << 16); // add x(p),x(p),x(isz)
+ *(uint32_t *)(cur_text_section->data + b1) =
+ (0x14000000 | (ind - b1) >> 2);
+ o(0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end)
+ o(0x54ffffa3 | ((lab1 - ind) << 3 & 0xffffe0)); // b.cc lab1
+ o(0xd5033b9f); // dsb ish
+ o(0xd5033fdf); // isb
+}
+
ST_FUNC void gen_vla_sp_save(int addr) {
tcc_error("variable length arrays unsupported for this target");
}
diff --git a/lib/lib-arm64.c b/lib/lib-arm64.c
index fd73506..bff1d91 100644
--- a/lib/lib-arm64.c
+++ b/lib/lib-arm64.c
@@ -14,7 +14,7 @@
void __clear_cache(char *beg, char *end)
{
-#warning __clear_cache not yet implemented
+ __arm64_clear_cache(beg, end);
}
typedef struct {
diff --git a/tcc.h b/tcc.h
index 33a827a..7d53b9b 100644
--- a/tcc.h
+++ b/tcc.h
@@ -1387,6 +1387,7 @@ ST_FUNC void gen_opl(int op);
ST_FUNC void greturn(void);
ST_FUNC void gen_va_start(void);
ST_FUNC void gen_va_arg(CType *t);
+ST_FUNC void gen_clear_cache(void);
#endif
/* ------------ c67-gen.c ------------ */
diff --git a/tccgen.c b/tccgen.c
index adc5005..52541e2 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -3979,6 +3979,18 @@ ST_FUNC void unary(void)
vtop->type = type;
break;
}
+ case TOK___arm64_clear_cache: {
+ next();
+ skip('(');
+ expr_eq();
+ skip(',');
+ expr_eq();
+ skip(')');
+ gen_clear_cache();
+ vpushi(0);
+ vtop->type.t = VT_VOID;
+ break;
+ }
#endif
case TOK_INC:
diff --git a/tcctok.h b/tcctok.h
index d78eb93..cfc87b3 100644
--- a/tcctok.h
+++ b/tcctok.h
@@ -244,6 +244,7 @@
DEF(TOK___chkstk, "__chkstk")
#endif
#ifdef TCC_TARGET_ARM64
+ DEF(TOK___arm64_clear_cache, "__arm64_clear_cache")
DEF(TOK___addtf3, "__addtf3")
DEF(TOK___subtf3, "__subtf3")
DEF(TOK___multf3, "__multf3")