Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ARM] vfp: fix fuitod/fsitod instructions

These two instructions exceptionally take a single precision register
as their operand. This means we can't use vfp_get_dm() to read the
register number - we need to use vfp_get_sm() instead. Add a flag to
indicate this exception to the general rule.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Russell King and committed by
Russell King
90e6b048 198a6d5a

+13 -3
+2
arch/arm/vfp/vfp.h
··· 361 361 * OP_SCALAR - this operation always operates in scalar mode 362 362 * OP_SD - the instruction exceptionally writes to a single precision result. 363 363 * OP_DD - the instruction exceptionally writes to a double precision result. 364 + * OP_SM - the instruction exceptionally reads from a single precision operand. 364 365 */ 365 366 #define OP_SCALAR (1 << 0) 366 367 #define OP_SD (1 << 1) 367 368 #define OP_DD (1 << 1) 369 + #define OP_SM (1 << 2) 368 370 369 371 struct op { 370 372 u32 (* const fn)(int dd, int dn, int dm, u32 fpscr);
+11 -3
arch/arm/vfp/vfpdouble.c
··· 668 668 [FEXT_TO_IDX(FEXT_FCMPZ)] = { vfp_double_fcmpz, OP_SCALAR }, 669 669 [FEXT_TO_IDX(FEXT_FCMPEZ)] = { vfp_double_fcmpez, OP_SCALAR }, 670 670 [FEXT_TO_IDX(FEXT_FCVT)] = { vfp_double_fcvts, OP_SCALAR|OP_SD }, 671 - [FEXT_TO_IDX(FEXT_FUITO)] = { vfp_double_fuito, OP_SCALAR }, 672 - [FEXT_TO_IDX(FEXT_FSITO)] = { vfp_double_fsito, OP_SCALAR }, 671 + [FEXT_TO_IDX(FEXT_FUITO)] = { vfp_double_fuito, OP_SCALAR|OP_SM }, 672 + [FEXT_TO_IDX(FEXT_FSITO)] = { vfp_double_fsito, OP_SCALAR|OP_SM }, 673 673 [FEXT_TO_IDX(FEXT_FTOUI)] = { vfp_double_ftoui, OP_SCALAR|OP_SD }, 674 674 [FEXT_TO_IDX(FEXT_FTOUIZ)] = { vfp_double_ftouiz, OP_SCALAR|OP_SD }, 675 675 [FEXT_TO_IDX(FEXT_FTOSI)] = { vfp_double_ftosi, OP_SCALAR|OP_SD }, ··· 1128 1128 u32 exceptions = 0; 1129 1129 unsigned int dest; 1130 1130 unsigned int dn = vfp_get_dn(inst); 1131 - unsigned int dm = vfp_get_dm(inst); 1131 + unsigned int dm; 1132 1132 unsigned int vecitr, veclen, vecstride; 1133 1133 struct op *fop; 1134 1134 ··· 1144 1144 dest = vfp_get_sd(inst); 1145 1145 else 1146 1146 dest = vfp_get_dd(inst); 1147 + 1148 + /* 1149 + * f[us]ito takes a sN operand, not a dN operand. 1150 + */ 1151 + if (fop->flags & OP_SM) 1152 + dm = vfp_get_sm(inst); 1153 + else 1154 + dm = vfp_get_dm(inst); 1147 1155 1148 1156 /* 1149 1157 * If destination bank is zero, vector length is always '1'.