summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDino Li <Dino.Li@ite.com.tw>2018-09-12 10:25:47 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-09-17 08:41:02 -0700
commit0941ed98c2b6edfb0013a2c913bc0d863eac63f0 (patch)
tree398589d25a378ca7654d3fc6ad9f31db83ea3cbe
parentd6fc44599ace6d92b41ab930b6a6b02ae00a4689 (diff)
downloadchrome-ec-0941ed98c2b6edfb0013a2c913bc0d863eac63f0.tar.gz
it83xx/fpu: fix floating-point multiplication issue for DX version.
Floating-point multiplication single-precision is failed on DX version, so we use the formula "A/(1/B)" to replace a multiplication operation (A*B = A/(1/B)). BUG=b:112452221 BRANCH=none TEST=add a console command and test different scenarios by changing variable a and b. static int it83xx_fpu_mul(int argc, char **argv) { volatile float a = 1.23f; volatile float b = 4.56f; volatile float c; c = a * b; ccprintf("__mulsf3: (%d)\n", PRINTF_FLOAT(c)); return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(mul, it83xx_fpu_mul, "", ""); Change-Id: I9e7d8477cf517b8df2975df9abb02a6387dc659b Signed-off-by: Dino Li <Dino.Li@ite.com.tw> Reviewed-on: https://chromium-review.googlesource.com/1201640 Reviewed-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
-rw-r--r--chip/it83xx/config_chip.h7
-rw-r--r--chip/it83xx/it83xx_fpu.S64
2 files changed, 71 insertions, 0 deletions
diff --git a/chip/it83xx/config_chip.h b/chip/it83xx/config_chip.h
index 21139cd7a4..1266353dcd 100644
--- a/chip/it83xx/config_chip.h
+++ b/chip/it83xx/config_chip.h
@@ -90,6 +90,13 @@
/* TODO(b/111264984): watchdog hardware reset function failed. */
#undef IT83XX_ETWD_HW_RESET_SUPPORT
/*
+ * (b/112452221):
+ * Floating-point multiplication single-precision is failed on DX version,
+ * so we use the formula "A/(1/B)" to replace a multiplication operation
+ * (A*B = A/(1/B)).
+ */
+#define IT83XX_FPU_MUL_BY_DIV
+/*
* More GPIOs can be set as 1.8v input.
* Please refer to gpio_1p8v_sel[] for 1.8v GPIOs.
*/
diff --git a/chip/it83xx/it83xx_fpu.S b/chip/it83xx/it83xx_fpu.S
index d98ba0fa67..5265eb7253 100644
--- a/chip/it83xx/it83xx_fpu.S
+++ b/chip/it83xx/it83xx_fpu.S
@@ -3,6 +3,8 @@
* found in the LICENSE file.
*/
+#include "config_chip.h"
+
/*
* DLMB register = 0x80189:
* Disable all interrupts and switching CPU's
@@ -51,6 +53,67 @@ __subsf3:
.global __mulsf3
.type __mulsf3, @function
__mulsf3:
+#ifdef IT83XX_FPU_MUL_BY_DIV
+#define SIGN $r2
+#define EXPOA $r3
+#define MANTA $r4
+#define VALUA $r5
+#define EXPOB $r6
+#define MANTB $r7
+#define VALUB $r8
+#define SPROD $r15
+ /* save r6-r8 */
+ smw.adm $r6, [$sp], $r8, #0x0
+ xor SPROD, $r1, $r0 /* sign(A xor B) */
+ move SIGN, #0x80000000
+ and SPROD, SPROD, SIGN /* store sign bit */
+ slli VALUA, $r0, 1 /* A<<1, (exponent and mantissa) */
+ slli VALUB, $r1, 1 /* B<<1, (exponent and mantissa) */
+ srli EXPOA, VALUA, 24 /* exponent(A) */
+ srli EXPOB, VALUB, 24 /* exponent(B) */
+ slli MANTA, VALUA, 7 /* A<<8, mantissa(A) with exponent's LSB */
+ slli MANTB, VALUB, 7 /* A<<8, mantissa(B) with exponent's LSB */
+ beqz VALUA, .LFzeroA /* exponent(A) and mantissa (A) are zero */
+ beqc EXPOA, 0xff, .LFinfnanA /* A is inf or NaN */
+ beqz VALUB, .LFzeroB /* exponent(B) and mantissa (B) are zero */
+ beqc EXPOB, 0xff, .LFinfnanB /* B is inf or NaN */
+ /* A*B = A/(1/B) */
+ sethi $r2, 0x80 /* r2 = 0x80000 */
+ addi $r3, $r2, 0x189 /* r3 = 0x80189 */
+ addi45 $r2, 0x9 /* r2 = 0x80009 */
+ mtsr $r3, $dlmb /* dlmb = 0x80189 */
+ dsb
+ sethi $r5, #0x3f800 /* r5 = 1.0f */
+ divsr $r1,$r1,$r5,$r1 /* r1 = 1.0f / r1 */
+ divsr $r0,$r0,$r0,$r1 /* r0 = r0 / r1 */
+ mtsr $r2, $dlmb /* dlmb = 0x80009 */
+ dsb
+.LFret:
+ /* restore r6-r8 */
+ lmw.bim $r6, [$sp], $r8, #0x0
+ ret5 $lp
+
+.LFzeroA: /* A is zero */
+ beqc EXPOB, 0xff, .LFnan/*zero * inf = zero * NaN = NaN */
+.LFzero:
+ move $r0, SPROD /* return 0.0f or -0.0f */
+ b .LFret
+.LFinfnanA: /* exponent(A) is 0xff */
+ bne MANTA, SIGN, .LFnan/* A is NaN: NaN * B = NaN */
+ beqz VALUB, .LFnan /* A is inf and B is zero: inf * zero = NaN */
+ bnec EXPOB, 0xff, .LFinf/* B is finite: inf * B = inf */
+.LFinfnanB: /* exponent(B) is 0xff */
+ bne MANTB, SIGN, .LFnan/* B is NaN: A * NaN = NaN */
+.LFinf:
+ move $r0, #0x7f800000
+ or $r0, $r0, SPROD /* return inf or -inf */
+ b .LFret
+.LFzeroB: /* B is zero and A is finit */
+ b .LFzero /* B is zero */
+.LFnan:
+ move $r0, #0xffc00000 /* return NaN */
+ b .LFret
+#else /* !IT83XX_FPU_MUL_BY_DIV */
sethi $r2, 0x80 /* r2 = 0x80000 */
addi $r3, $r2, 0x189 /* r3 = 0x80189 */
addi45 $r2, 0x9 /* r2 = 0x80009 */
@@ -61,6 +124,7 @@ __mulsf3:
mtsr $r2, $dlmb /* dlmb = 0x80009 */
dsb
ret5 $lp
+#endif /* IT83XX_FPU_MUL_BY_DIV */
.size __mulsf3, .-__mulsf3
.text