From 52bd35da458199cabdc308508d28946b9f4d8e87 Mon Sep 17 00:00:00 2001
From: svofski <[email protected]>
Date: Wed, 2 Dec 2020 22:41:57 +0300
Subject: [PATCH] support optional udiv and umod instructions
Opcodes 32 udiv, 33 umod. They are not standard and disabled by default.
Enable them with -mudiv -mumod.
---
toolchain/binutils/include/opcode/zpu.h | 2 ++
toolchain/binutils/opcodes/zpu-opc.c | 2 ++
toolchain/gcc/gcc/config/zpu/zpu.c | 16 ++++++++++++++++
toolchain/gcc/gcc/config/zpu/zpu.h | 11 +++++++++--
4 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/toolchain/binutils/include/opcode/zpu.h b/toolchain/binutils/include/opcode/zpu.h
index ae740f3d..777421c2 100755
--- a/toolchain/binutils/include/opcode/zpu.h
+++ b/toolchain/binutils/include/opcode/zpu.h
@@ -80,6 +80,8 @@ enum ZPU_OPCODE
ZPU_pushspadd=61,
ZPU_halfmult=62,
ZPU_callpcrel=63,
+ ZPU_udiv=32,
+ ZPU_umod=33,
ZPU_impcrel=0, /* not an opcode, translates to IM instructions */
diff --git a/toolchain/binutils/opcodes/zpu-opc.c b/toolchain/binutils/opcodes/zpu-opc.c
index cf784838..97dcfa40 100755
--- a/toolchain/binutils/opcodes/zpu-opc.c
+++ b/toolchain/binutils/opcodes/zpu-opc.c
@@ -58,6 +58,8 @@ const struct zpu_opcode zpu_opcodes[]={
{ZPU_swap, "swap", ADDR_IMPLIED},
{ZPU_div, "div", ADDR_IMPLIED},
{ZPU_mod, "mod", ADDR_IMPLIED},
+ {ZPU_udiv, "udiv", ADDR_IMPLIED},
+ {ZPU_umod, "umod", ADDR_IMPLIED},
{ZPU_eqbranch, "eqbranch", ADDR_IMPLIED},
{ZPU_neqbranch, "neqbranch", ADDR_IMPLIED},
diff --git a/toolchain/gcc/gcc/config/zpu/zpu.c b/toolchain/gcc/gcc/config/zpu/zpu.c
index df6c787e..1fe8bbbb 100755
--- a/toolchain/gcc/gcc/config/zpu/zpu.c
+++ b/toolchain/gcc/gcc/config/zpu/zpu.c
@@ -551,6 +551,10 @@ int zpu_binary_operator (rtx op ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIB
return TARGET_DIV;
case MOD:
return TARGET_MOD;
+ case UDIV:
+ return TARGET_UDIV;
+ case UMOD:
+ return TARGET_UMOD;
default:
break;
@@ -1692,12 +1696,24 @@ static void push_operand_value(rtx *operand)
push_operand_value(&XEXP (*operand, 0));
zpu_asm("div", operand);
stackOffset+=4;
+ } else if (GET_CODE(operand[0]) == UDIV)
+ {
+ push_operand_value(&XEXP (*operand, 1));
+ push_operand_value(&XEXP (*operand, 0));
+ zpu_asm("udiv", operand);
+ stackOffset+=4;
} else if (GET_CODE(operand[0])==MOD)
{
push_operand_value(&XEXP (*operand, 1));
push_operand_value(&XEXP (*operand, 0));
zpu_asm("mod", operand);
stackOffset+=4;
+ } else if (GET_CODE(operand[0])==UMOD)
+ {
+ push_operand_value(&XEXP (*operand, 1));
+ push_operand_value(&XEXP (*operand, 0));
+ zpu_asm("umod", operand);
+ stackOffset+=4;
} else if (GET_CODE(operand[0])==ZERO_EXTEND)
{
push_operand_value(&XEXP (*operand, 0));
diff --git a/toolchain/gcc/gcc/config/zpu/zpu.h b/toolchain/gcc/gcc/config/zpu/zpu.h
index 46483a08..7e7d5b95 100755
--- a/toolchain/gcc/gcc/config/zpu/zpu.h
+++ b/toolchain/gcc/gcc/config/zpu/zpu.h
@@ -92,11 +92,13 @@ extern int target_flags;
#define ZPU_BITSBIG (1<<24)
#define ZPU_MEMREG (1<<25)
+#define ZPU_UDIV (1<<26)
+#define ZPU_UMOD (1<<27)
-#define TARGET_SWITCHES_DEFAULT (0x7fffffff&~ZPU_BITSBIG)
+#define TARGET_SWITCHES_DEFAULT (0x7fffffff&~(ZPU_BITSBIG|ZPU_UDIV|ZPU_UMOD))
@@ -123,7 +125,8 @@ extern int target_flags;
#define TARGET_BYTESBIG ((target_flags & ZPU_BYTESBIG)!=0)
#define TARGET_BITSBIG ((target_flags & ZPU_BITSBIG)!=0)
#define TARGET_MEMREG ((target_flags & ZPU_MEMREG)!=0)
-
+#define TARGET_UDIV ((target_flags & ZPU_UDIV)!=0)
+#define TARGET_UMOD ((target_flags & ZPU_UMOD)!=0)
#define TARGET_SWITCHES \
{ \
@@ -133,6 +136,10 @@ extern int target_flags;
{ "no-div", -ZPU_DIV, "DIV instruction" },\
{ "mod", ZPU_MOD, "MOD instruction" },\
{ "no-mod", -ZPU_MOD, "MOD instruction" },\
+ { "udiv", ZPU_UDIV, "UDIV instruction" },\
+ { "no-udiv", -ZPU_UDIV, "UDIV instruction" },\
+ { "umod", ZPU_UMOD, "UMOD instruction" },\
+ { "no-umod", -ZPU_UMOD, "UMOD instruction" },\
{ "neg", ZPU_NEG, "NEG instruction" },\
{ "no-neg", -ZPU_NEG, "NEG instruction" },\
{ "loadsp", ZPU_LOADSP, "LOADSP instruction" },\
--
2.25.1