diff options
author | Dino Li <Dino.Li@ite.com.tw> | 2018-09-12 10:25:47 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-09-17 08:41:02 -0700 |
commit | 0941ed98c2b6edfb0013a2c913bc0d863eac63f0 (patch) | |
tree | 398589d25a378ca7654d3fc6ad9f31db83ea3cbe /chip | |
parent | d6fc44599ace6d92b41ab930b6a6b02ae00a4689 (diff) | |
download | chrome-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>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/it83xx/config_chip.h | 7 | ||||
-rw-r--r-- | chip/it83xx/it83xx_fpu.S | 64 |
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 |