From 2616c6b230ff4bd6d68019a11f6b0e1133709456 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sun, 21 Jul 2019 05:39:35 +0200 Subject: [PATCH] riscv: Fix 73_arm.c some constants were loaded wrong (e.g. 0xffffabcdU), and risc-v needs to do explicit zero-extensions for widening from 32bit (not sign-extensions like the other 64bit targets). This makes the whole tests2.all testsuite work. Parameter passing is still not psABI-compliant, but internally consistent. (e.g. structs of two floats/doubles are passed in integer registers, but should sit in float regs). --- riscv64-gen.c | 22 ++++++++++------------ tccgen.c | 10 ++++++++++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/riscv64-gen.c b/riscv64-gen.c index 3eb77e1a..2e121769 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -203,8 +203,8 @@ ST_FUNC void load(int r, SValue *sv) tcc_error("unimp: load(non-local lval)"); } } else if (v == VT_CONST) { - int rb = 0, do32bit = 8, doload = 0; - assert(!is_float(sv->type.t) && is_ireg(r) || bt == VT_LDOUBLE); + int rb = 0, do32bit = 8, doload = 0, zext = 0; + assert((!is_float(sv->type.t) && is_ireg(r)) || bt == VT_LDOUBLE); if (fr & VT_SYM) { static Sym label; if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax @@ -252,16 +252,10 @@ ST_FUNC void load(int r, SValue *sv) fc &= 0xff; rb = rr; do32bit = 0; - } else { - /* A 32bit unsigned constant. lui always sign extends, so we need - tricks. */ - pi = (uint32_t)sv->c.i; - o(0x37 | (rr << 7) | (((pi + 0x80000) & 0xfff00000) >> 8)); // lui RR, up(fc)>>8 - EI(0x13, 0, rr, rr, (((pi + 0x200) & 0x000ffc00) >> 8) | (-((int)(pi + 0x200) & 0x80000) >> 8)); // addi RR, RR, mid(fc) - EI(0x13, 1, rr, rr, 8); // slli RR, RR, 8 - fc = (pi & 0x3ff) | (-((int)(pi & 0x200))); - rb = rr; - do32bit = 0; + } else if (bt == VT_LLONG) { + /* A 32bit unsigned constant for a 64bit type. + lui always sign extends, so we need to do an explicit zext.*/ + zext = 1; } } if (((unsigned)fc + (1 << 11)) >> 12) @@ -272,6 +266,10 @@ ST_FUNC void load(int r, SValue *sv) EI(0x13 | do32bit, 0, rr, rr, fc << 20 >> 20); // addi[w] R, x0|R, FC } else EI(0x13 | do32bit, 0, rr, rb, fc << 20 >> 20); // addi[w] R, x0|R, FC + if (zext) { + EI(0x13, 1, rr, rr, 32); // slli RR, RR, 32 + EI(0x13, 5, rr, rr, 32); // srli RR, RR, 32 + } } else if (v == VT_LOCAL) { int br = 8; // s0 assert(is_ireg(r)); diff --git a/tccgen.c b/tccgen.c index 66042c3d..31c1655b 100644 --- a/tccgen.c +++ b/tccgen.c @@ -2834,6 +2834,16 @@ static void gen_cast(CType *type) o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r)); #else #error +#endif + } else if (sbt & VT_UNSIGNED) { +#if defined(TCC_TARGET_RISCV64) + /* RISC-V keeps 32bit vals in registers sign-extended. + So here we need a zero-extension. */ + vtop->type.t = dbt; + vpushi(32); + gen_op(TOK_SHL); + vpushi(32); + gen_op(TOK_SHR); #endif } }