summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/it83xx/config_chip_it8xxx2.h7
-rw-r--r--core/riscv-rv32i/__it8xxx2_arithmetic.S45
-rw-r--r--core/riscv-rv32i/build.mk1
-rw-r--r--include/config.h6
-rw-r--r--util/config_allowed.txt1
5 files changed, 60 insertions, 0 deletions
diff --git a/chip/it83xx/config_chip_it8xxx2.h b/chip/it83xx/config_chip_it8xxx2.h
index 3f715380ac..345a248867 100644
--- a/chip/it83xx/config_chip_it8xxx2.h
+++ b/chip/it83xx/config_chip_it8xxx2.h
@@ -86,6 +86,13 @@
#define CONFIG_RAM_BASE 0x80100000
#define CONFIG_RAM_SIZE 0x0000f000
+/*
+ * Workaround mul instruction bug, see:
+ * https://www.ite.com.tw/uploads/product_download/it81202-bx-chip-errata.pdf
+ */
+#undef CONFIG_RISCV_EXTENSION_M
+#define CONFIG_IT8XXX2_MUL_WORKAROUND
+
/* Embedded flash is KGD */
#define IT83XX_CHIP_FLASH_IS_KGD
/* Set ILM (instruction local memory) size up to 1M bytes */
diff --git a/core/riscv-rv32i/__it8xxx2_arithmetic.S b/core/riscv-rv32i/__it8xxx2_arithmetic.S
new file mode 100644
index 0000000000..8e477863fc
--- /dev/null
+++ b/core/riscv-rv32i/__it8xxx2_arithmetic.S
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022 The ChromiumOS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * When the 'M' extension is disabled, compiler can not recognize div/mul
+ * instructions. So mul/div instructions in the below integer arithmetic
+ * routines are hard coded by opcodes.
+ *
+ * IMPORTANT:
+ * The workaround requires the nop instruction, please don't optimize it.
+ */
+
+.macro __int_arithmetic func opcode
+.section .ram_code_ilm0
+.align 2
+.globl \func
+.type \func, @function
+\func:
+.word \opcode
+nop
+ret
+.size \func, .-\func
+.endm
+
+/* signed 32 bit multiplication. opcode of mul a0,a0,a1 is 0x02b50533 */
+__int_arithmetic __mulsi3 0x02b50533
+
+/* signed 32 bit division. opcode of div a0,a0,a1 is 0x02b54533 */
+__int_arithmetic __divsi3 0x02b54533
+
+/* unsigned 32 bit division. opcode of divu a0,a0,a1 is 0x02b55533 */
+__int_arithmetic __udivsi3 0x02b55533
+
+/*
+ * This function return the remainder of the signed division.
+ * opcode of rem a0,a0,a1 is 0x02b56533
+ */
+__int_arithmetic __modsi3 0x02b56533
+
+/*
+ * This function return the remainder of the unsigned division.
+ * opcode of remu a0,a0,a1 is 0x02b57533
+ */
+__int_arithmetic __umodsi3 0x02b57533
diff --git a/core/riscv-rv32i/build.mk b/core/riscv-rv32i/build.mk
index 376bd2c093..7e5ce0e8a7 100644
--- a/core/riscv-rv32i/build.mk
+++ b/core/riscv-rv32i/build.mk
@@ -30,3 +30,4 @@ LDFLAGS_EXTRA+=-flto
endif
core-y=cpu.o init.o panic.o task.o switch.o __builtin.o math.o
+core-$(CONFIG_IT8XXX2_MUL_WORKAROUND)+=__it8xxx2_arithmetic.o
diff --git a/include/config.h b/include/config.h
index ee84db0291..cb364d5516 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2643,6 +2643,12 @@
#undef CONFIG_IT83XX_VCC_3P3V
/*
+ * Overwrite integer multiplication and division arithmetic library routines
+ * with using hardware multiplication and division and nop instructions.
+ */
+#undef CONFIG_IT8XXX2_MUL_WORKAROUND
+
+/*
* Support the standard integer multiplication and division instruction
* extension.
*/
diff --git a/util/config_allowed.txt b/util/config_allowed.txt
index e28bd5f39c..3405570a72 100644
--- a/util/config_allowed.txt
+++ b/util/config_allowed.txt
@@ -609,6 +609,7 @@ CONFIG_IT83XX_SMCLK2_ON_GPC7
CONFIG_IT83XX_TUNE_CC_PHY
CONFIG_IT83XX_VCC_1P8V
CONFIG_IT83XX_VCC_3P3V
+CONFIG_IT8XXX2_MUL_WORKAROUND
CONFIG_ITE_FLASH_SUPPORT
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT
CONFIG_KEYBOARD_ASSISTANT_KEY