aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2019-03-15 23:18:29 +0100
committerClifford Wolf <clifford@clifford.at>2019-03-15 23:18:29 +0100
commitd3c0e2ad3e41e132b8858bbb7dd8fbcbd2b43b22 (patch)
tree303a5439ddad9f0a623b60f28dd894afc3a51c88
parent6d145b708d5dfa4caa3445bc599927cebc3291d8 (diff)
downloadpicorv32-d3c0e2ad3e41e132b8858bbb7dd8fbcbd2b43b22.tar.gz
picorv32-d3c0e2ad3e41e132b8858bbb7dd8fbcbd2b43b22.zip
Import GCC hack
Signed-off-by: Clifford Wolf <clifford@clifford.at>
-rw-r--r--Makefile3
-rw-r--r--riscv-gcc-hack.patch275
2 files changed, 277 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index b2b019e..1a4c6c9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
RISCV_GNU_TOOLCHAIN_GIT_REVISION = 411d134
-RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX = /opt/riscv32
+RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX = /opt/riscv32hacked_
SHELL = bash
TEST_OBJS = $(addsuffix .o,$(basename $(wildcard tests/*.S)))
@@ -142,6 +142,7 @@ build-$(1)-tools-bh:
git submodule update --init $$$$reference_riscv_gcc riscv-gcc; \
git submodule update --init $$$$reference_riscv_glibc riscv-glibc; \
git submodule update --init $$$$reference_riscv_newlib riscv-newlib; \
+ cd riscv-gcc; patch -p1 < ../../riscv-gcc-hack.patch; cd ..; \
mkdir build; cd build; ../configure --with-arch=$(2) --prefix=$(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)$(subst riscv32,,$(1)); make
.PHONY: build-$(1)-tools
diff --git a/riscv-gcc-hack.patch b/riscv-gcc-hack.patch
new file mode 100644
index 0000000..136d3b8
--- /dev/null
+++ b/riscv-gcc-hack.patch
@@ -0,0 +1,275 @@
+diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
+index 76bb74fb2d4..6b8eea0235a 100644
+--- a/gcc/config/riscv/riscv.c
++++ b/gcc/config/riscv/riscv.c
+@@ -1358,6 +1358,9 @@ riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
+ /* If (set DEST SRC) is not a valid move instruction, emit an equivalent
+ sequence that is valid. */
+
++bool riscv_legitimize_qimove (rtx dest, rtx src);
++bool riscv_legitimize_himove (rtx dest, rtx src);
++
+ bool
+ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
+ {
+@@ -1367,6 +1370,12 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
+ return true;
+ }
+
++ if ((mode == QImode) && (MEM_P(dest)) )
++ return riscv_legitimize_qimove(dest, src);
++ if ((mode == HImode) && (MEM_P(dest)) )
++ return riscv_legitimize_himove(dest, src);
++
++
+ /* We need to deal with constants that would be legitimate
+ immediate_operands but aren't legitimate move_operands. */
+ if (CONSTANT_P (src) && !move_operand (src, mode))
+@@ -1395,6 +1404,197 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
+ return false;
+ }
+
++bool
++riscv_legitimize_qimove (rtx dest, rtx src)
++{
++ /*
++ {
++ t = *(p&~3)
++ nv = v << ((p&3)<<3)
++ msk = 255 << ((p&3)<<3)
++ t &= ~msk
++ t |= nv
++ *(p^~3) = t
++
++ ////////////
++ // After some simplifications becomes
++ ////////////
++
++ // R0 = p
++ // R1 = v
++ na = *(p&~3) Ra = na
++ sft = (p&3)<<3; Rb = sft, then t
++ msk = 255 Rm = msk
++ nv &= v & msk Rd = nv
++ nv<<= sft
++ msk<<= sft
++ msk = ~msk
++ t = *na
++ t &= msk
++ t |= nv
++
++ ////////////
++ // After some simplifications becomes
++ ////////////
++ }
++ */
++
++ // ANDI Ra,R0,~3 // Calculate the new address
++ // ANDI Rb,R0,3
++ // SLLI Rb,Rb,3
++ // LUI Rm,255
++ // AND Rd,R1,Rm
++ // SLL Rd,Rd,Rb
++ // SLL Rm,Rm,Rb
++ // XORI Rm,Rm,-1 // Negate the mask
++ // LW Rb,Ra
++ // AND Rb,Rb,Rm
++ // OR Rb,Rb,Rd
++ // SW Ra,Rb
++ //
++ //
++ rtx Ra = gen_reg_rtx(Pmode), // Address
++ Rb = gen_reg_rtx(SImode),
++ Rm = gen_reg_rtx(SImode), // Mask
++ Rd = gen_reg_rtx(SImode), // Data
++ Rq = gen_reg_rtx(QImode), // Shift amount
++ addr,
++ mem; // = XEXP(src,0);
++
++ if (MEM_P (dest) && !REG_P(XEXP(dest,0))) {
++ addr = gen_reg_rtx(Pmode);
++ emit_insn(gen_rtx_SET(addr, XEXP(dest, 0)));
++ } else
++ addr = XEXP(dest, 0);
++
++ mem = gen_rtx_MEM(SImode, Ra);
++
++ if (Pmode == DImode) {
++ emit_insn(gen_rtx_SET(Rb, gen_rtx_SUBREG(SImode, addr, 0)));
++ emit_insn(gen_andsi3(Rm, Rb, gen_int_mode(~3, Pmode)));
++ emit_insn(gen_rtx_SET(gen_rtx_SUBREG(SImode, Ra, 0), Rm));
++ emit_insn(gen_rtx_SET(gen_rtx_SUBREG(SImode, Ra, 1),
++ gen_rtx_SUBREG(SImode, addr, 1)));
++
++ emit_insn(gen_andsi3(Rb, Rb, gen_int_mode( 3, SImode)));
++ } else {
++ emit_insn(gen_andsi3(Ra, addr, gen_int_mode(~3, SImode)));
++ emit_insn(gen_andsi3(Rb, addr, gen_int_mode( 3, SImode)));
++ }
++ emit_insn(gen_ashlsi3(Rb, Rb, gen_int_mode( 3, SImode)));
++ emit_insn(gen_movsi(Rm, gen_int_mode(255, SImode)));
++ if (QImode == GET_MODE(src))
++ emit_insn(gen_rtx_SET(Rd, gen_rtx_ZERO_EXTEND(SImode, src)));
++ else
++ emit_insn(gen_rtx_SET(Rd, src));
++ // emit_insn(gen_andsi3(Rd, Rd, Rm));
++ emit_insn(gen_rtx_SET(Rq, gen_rtx_SUBREG(QImode, Rb, 0)));
++ emit_insn(gen_ashlsi3(Rd, Rd, Rq));
++ emit_insn(gen_ashlsi3(Rm, Rm, Rq));
++ emit_insn(gen_xorsi3(Rm, Rm, gen_int_mode(-1, SImode)));
++ emit_insn(gen_movsi(Rb, mem));
++ emit_insn(gen_andsi3(Rb, Rb, Rm));
++ emit_insn(gen_iorsi3(Rb, Rb, Rd));
++ emit_insn(gen_movsi(mem, Rb));
++
++ return true;
++}
++
++bool
++riscv_legitimize_himove (rtx dest, rtx src)
++{
++ /*
++ {
++ t = *(p&~3)
++ nv = v << ((p&3)<<3)
++ msk = 65535 << ((p&3)<<3)
++ t &= ~msk
++ t |= nv
++ *(p^~3) = t
++
++ ////////////
++ // After some simplifications becomes
++ ////////////
++
++ // R0 = p
++ // R1 = v
++ na = *(p&~3) Ra = na
++ sft = (p&2)<<3; Rb = sft, then t
++ msk = 65535 Rm = msk
++ nv &= v & msk Rd = nv
++ nv<<= sft
++ msk<<= sft
++ msk = ~msk
++ t = *na
++ t &= msk
++ t |= nv
++
++ ////////////
++ // After some simplifications becomes
++ ////////////
++ }
++ */
++
++ // ANDI Ra,R0,~3 // Calculate the new address
++ // ANDI Rb,R0,3
++ // SLLI Rb,Rb,3
++ // LUI Rm,255
++ // AND Rd,R1,Rm
++ // SLL Rd,Rd,Rb
++ // SLL Rm,Rm,Rb
++ // XORI Rm,Rm,-1 // Negate the mask
++ // LW Rb,Ra
++ // AND Rb,Rb,Rm
++ // OR Rb,Rb,Rd
++ // SW Ra,Rb
++ //
++ //
++ rtx Ra = gen_reg_rtx(Pmode), // Address
++ Rb = gen_reg_rtx(SImode),
++ Rm = gen_reg_rtx(SImode), // Mask
++ Rd = gen_reg_rtx(SImode), // Data
++ Rq = gen_reg_rtx(QImode), // Shift amount
++ addr,
++ mem; // = XEXP(src,0);
++
++ if (MEM_P (dest) && !REG_P(XEXP(dest,0))) {
++ addr = gen_reg_rtx(Pmode);
++ emit_insn(gen_rtx_SET(addr, XEXP(dest, 0)));
++ } else
++ addr = XEXP(dest, 0);
++
++ mem = gen_rtx_MEM(SImode, Ra);
++
++ if (DImode == Pmode) {
++ emit_insn(gen_rtx_SET(Rb, gen_rtx_SUBREG(SImode, addr, 0)));
++ emit_insn(gen_andsi3(Rm, Rb, gen_int_mode(~3, SImode)));
++ emit_insn(gen_movsi(gen_rtx_SUBREG(SImode, Ra, 0), Rm));
++ emit_insn(gen_movsi(gen_rtx_SUBREG(SImode, Ra, 1),
++ gen_rtx_SUBREG(SImode, addr, 1)));
++
++ emit_insn(gen_andsi3(Rb, Rb, gen_int_mode( 2, SImode)));
++ } else {
++ emit_insn(gen_andsi3(Ra, addr, gen_int_mode(~3, Pmode)));
++ emit_insn(gen_andsi3(Rb, addr, gen_int_mode( 2, SImode)));
++ }
++ emit_insn(gen_ashlsi3(Rb, Rb, gen_int_mode( 3, SImode)));
++ emit_insn(gen_movsi(Rm, gen_int_mode(65535, SImode)));
++ if (HImode == GET_MODE(src))
++ emit_insn(gen_rtx_SET(Rd, gen_rtx_ZERO_EXTEND(SImode, src)));
++ else
++ emit_insn(gen_rtx_SET(Rd, src));
++ emit_insn(gen_rtx_SET(Rq, gen_rtx_SUBREG(QImode, Rb, 0)));
++ emit_insn(gen_ashlsi3(Rd, Rd, Rq));
++ emit_insn(gen_ashlsi3(Rm, Rm, Rq));
++ emit_insn(gen_xorsi3(Rm, Rm, gen_int_mode(-1, SImode)));
++ emit_insn(gen_movsi(Rb, mem));
++ emit_insn(gen_andsi3(Rb, Rb, Rm));
++ emit_insn(gen_iorsi3(Rb, Rb, Rd));
++ emit_insn(gen_movsi(mem, Rb));
++
++ return true;
++}
++
+ /* Return true if there is an instruction that implements CODE and accepts
+ X as an immediate operand. */
+
+diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
+index 668668fc2ab..ef88eaedc4a 100644
+--- a/gcc/config/riscv/riscv.md
++++ b/gcc/config/riscv/riscv.md
+@@ -1343,15 +1343,17 @@
+ {
+ if (riscv_legitimize_move (HImode, operands[0], operands[1]))
+ DONE;
++ if (MEM_P(operands[0]))
++ FAIL;
+ })
+
+ (define_insn "*movhi_internal"
+- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
+- (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f"))]
+- "(register_operand (operands[0], HImode)
+- || reg_or_0_operand (operands[1], HImode))"
++ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, *f,*r")
++ (match_operand:HI 1 "move_operand" " r,T,m,*r*J,*f"))]
++ "((!MEM_P(operands[0]))&&(register_operand (operands[0], HImode)
++ || reg_or_0_operand (operands[1], HImode)))"
+ { return riscv_output_move (operands[0], operands[1]); }
+- [(set_attr "move_type" "move,const,load,store,mtc,mfc")
++ [(set_attr "move_type" "move,const,load,mtc,mfc")
+ (set_attr "mode" "HI")])
+
+ ;; HImode constant generation; see riscv_move_integer for details.
+@@ -1385,15 +1387,17 @@
+ {
+ if (riscv_legitimize_move (QImode, operands[0], operands[1]))
+ DONE;
++ if (MEM_P(operands[0]))
++ FAIL;
+ })
+
+ (define_insn "*movqi_internal"
+- [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
+- (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f"))]
+- "(register_operand (operands[0], QImode)
+- || reg_or_0_operand (operands[1], QImode))"
++ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, *f,*r")
++ (match_operand:QI 1 "move_operand" " r,I,m,*r*J,*f"))]
++ "(!MEM_P(operands[0])&&(register_operand (operands[0], QImode)
++ || reg_or_0_operand (operands[1], QImode)))"
+ { return riscv_output_move (operands[0], operands[1]); }
+- [(set_attr "move_type" "move,const,load,store,mtc,mfc")
++ [(set_attr "move_type" "move,const,load,mtc,mfc")
+ (set_attr "mode" "QI")])
+
+ ;; 32-bit floating point moves