diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-01-10 12:07:08 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-01-10 12:07:08 -0500 |
commit | 90e6b048365950416419c031f2f2d9a8afb5b70c (patch) | |
tree | 9be821f3d0abf5d9773bb1d4f57f013be445fdac /arch/arm | |
parent | 198a6d5a6189501e2b8abf4e3149ccb337866f65 (diff) |
[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>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/vfp/vfp.h | 2 | ||||
-rw-r--r-- | arch/arm/vfp/vfpdouble.c | 14 |
2 files changed, 13 insertions, 3 deletions
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h index 54a2ad6d9ca2..791d0238c68f 100644 --- a/arch/arm/vfp/vfp.h +++ b/arch/arm/vfp/vfp.h | |||
@@ -361,10 +361,12 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); | |||
361 | * OP_SCALAR - this operation always operates in scalar mode | 361 | * OP_SCALAR - this operation always operates in scalar mode |
362 | * OP_SD - the instruction exceptionally writes to a single precision result. | 362 | * OP_SD - the instruction exceptionally writes to a single precision result. |
363 | * OP_DD - the instruction exceptionally writes to a double precision result. | 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 | #define OP_SCALAR (1 << 0) | 366 | #define OP_SCALAR (1 << 0) |
366 | #define OP_SD (1 << 1) | 367 | #define OP_SD (1 << 1) |
367 | #define OP_DD (1 << 1) | 368 | #define OP_DD (1 << 1) |
369 | #define OP_SM (1 << 2) | ||
368 | 370 | ||
369 | struct op { | 371 | struct op { |
370 | u32 (* const fn)(int dd, int dn, int dm, u32 fpscr); | 372 | u32 (* const fn)(int dd, int dn, int dm, u32 fpscr); |
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index 190a09ad18eb..6cac43bd1d86 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c | |||
@@ -668,8 +668,8 @@ static struct op fops_ext[32] = { | |||
668 | [FEXT_TO_IDX(FEXT_FCMPZ)] = { vfp_double_fcmpz, OP_SCALAR }, | 668 | [FEXT_TO_IDX(FEXT_FCMPZ)] = { vfp_double_fcmpz, OP_SCALAR }, |
669 | [FEXT_TO_IDX(FEXT_FCMPEZ)] = { vfp_double_fcmpez, OP_SCALAR }, | 669 | [FEXT_TO_IDX(FEXT_FCMPEZ)] = { vfp_double_fcmpez, OP_SCALAR }, |
670 | [FEXT_TO_IDX(FEXT_FCVT)] = { vfp_double_fcvts, OP_SCALAR|OP_SD }, | 670 | [FEXT_TO_IDX(FEXT_FCVT)] = { vfp_double_fcvts, OP_SCALAR|OP_SD }, |
671 | [FEXT_TO_IDX(FEXT_FUITO)] = { vfp_double_fuito, 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 }, | 672 | [FEXT_TO_IDX(FEXT_FSITO)] = { vfp_double_fsito, OP_SCALAR|OP_SM }, |
673 | [FEXT_TO_IDX(FEXT_FTOUI)] = { vfp_double_ftoui, OP_SCALAR|OP_SD }, | 673 | [FEXT_TO_IDX(FEXT_FTOUI)] = { vfp_double_ftoui, OP_SCALAR|OP_SD }, |
674 | [FEXT_TO_IDX(FEXT_FTOUIZ)] = { vfp_double_ftouiz, OP_SCALAR|OP_SD }, | 674 | [FEXT_TO_IDX(FEXT_FTOUIZ)] = { vfp_double_ftouiz, OP_SCALAR|OP_SD }, |
675 | [FEXT_TO_IDX(FEXT_FTOSI)] = { vfp_double_ftosi, OP_SCALAR|OP_SD }, | 675 | [FEXT_TO_IDX(FEXT_FTOSI)] = { vfp_double_ftosi, OP_SCALAR|OP_SD }, |
@@ -1128,7 +1128,7 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) | |||
1128 | u32 exceptions = 0; | 1128 | u32 exceptions = 0; |
1129 | unsigned int dest; | 1129 | unsigned int dest; |
1130 | unsigned int dn = vfp_get_dn(inst); | 1130 | unsigned int dn = vfp_get_dn(inst); |
1131 | unsigned int dm = vfp_get_dm(inst); | 1131 | unsigned int dm; |
1132 | unsigned int vecitr, veclen, vecstride; | 1132 | unsigned int vecitr, veclen, vecstride; |
1133 | struct op *fop; | 1133 | struct op *fop; |
1134 | 1134 | ||
@@ -1146,6 +1146,14 @@ u32 vfp_double_cpdo(u32 inst, u32 fpscr) | |||
1146 | dest = vfp_get_dd(inst); | 1146 | dest = vfp_get_dd(inst); |
1147 | 1147 | ||
1148 | /* | 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); | ||
1155 | |||
1156 | /* | ||
1149 | * If destination bank is zero, vector length is always '1'. | 1157 | * If destination bank is zero, vector length is always '1'. |
1150 | * ARM DDI0100F C5.1.3, C5.3.2. | 1158 | * ARM DDI0100F C5.1.3, C5.3.2. |
1151 | */ | 1159 | */ |