From d73b48840115f0adc97d6a9e6fe2aeb88fcbfbdd Mon Sep 17 00:00:00 2001 From: Edmund Grimley Evans Date: Sun, 8 Mar 2015 00:10:44 +0000 Subject: [PATCH] arm64: Implement __clear_cache. __clear_cache is defined in lib-arm64.c with a single call to __arm64_clear_cache, which is the real built-in function and is turned into inline assembler by gen_clear_cache in arm64-gen.c --- arm64-gen.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/lib-arm64.c | 2 +- tcc.h | 1 + tccgen.c | 12 ++++++++++++ tcctok.h | 1 + 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/arm64-gen.c b/arm64-gen.c index fe1a6341..3581e5d3 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 fd73506e..bff1d91a 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 33a827a5..7d53b9b1 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 adc5005c..52541e29 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 d78eb93d..cfc87b3e 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") -- 2.11.4.GIT