__PSQ_L / __PSQ_LX / __PSQ_ST / __PSQ_STX

Syntax

#include <ppc_ps.h>

f32x2 __PSQ_L(const void * __P, int __W, int __I);
f32x2 __PSQ_LX(const void * __P, int __O, int __W, int __I);

void __PSQ_ST(void * __P, f32x2 __D, int __W, int __I);
void __PSQ_STX(void * __P, int __O, f32x2 __D, int __W, int __I);

Parameters

_P Pointer to read/write memory.
_O Byte offset added to pointer.
__D f32x2 value to store.
_W 0: Load/store full f32x2.
1: Load/store PS0, and set PS1 to 1.0 on load.
_I 0-7 UGQR: Number to control conversion.

Return Values

__PSQ_L and __PSQ_LX return an f32x2 value.

__PSQ_ST and __PSQ_STX return nothing.

Description

Read and write paired single registers, with optional quantization.

User Graphics Quantization Registers (UGQRs)

Quantization is controlled by UGQR registers (SPRs 896 through 903) as follows.

Bits Field Name Description
0:1 -- Reserved.
2:7 LD_SCALE Scale value used by a load instruction.
8:12 -- Reserved.
13:15 LD_TYPE 0: Single-precision floating-point (no conversion)
1-3: Reserved
4: Unsigned 8-bit integer
5: Unsigned 16-bit integer
6: Signed 8-bit integer
7: Signed 16-bit integer
16:17 -- Reserved.
18:23 ST_SCALE Scale value used by a store instruction.
24:28 -- Reserved.
29:31 ST_TYPE 0: Single-precision floating-point (no conversion)
1-3: Reserved
4: Unsigned 8-bit integer
5: Unsigned 16-bit integer
6: Signed 8-bit integer
7: Signed 16-bit integer

UGQR registers can be set using the GHS intrinsic function __MTSPR, and read using __MFSPR.

#include <ppc_ghs.h>
#include <ppc_asm_user.h>

u32 oldgqr;
oldgqr = __MFSPR(UGQR7);
__MTSPR(UGQR7, 0x02060206); /* read s8 scale by 0.25, write s8 scale by 4 */
NOTE:
UGQR0 should always be set to 0 (no conversions or scaling).
NOTE:
UGQR1 is reserved for the compiler to use.
NOTE:
UGQR2-UGQR4 are used by OSFastCast functions:

OSf32tos16
OSf32tos8
OSf32tou16
OSf32tou8
OSs16tof32
OSs8tof32
OSu16tof32
OSu8tof32

If you modify UGQR2-UGQR4, reset to default values by calling OSInitFastCast.

The LD_SCALE field of the UGQR is only used when loading an integer type, result = I * 2-S.

Table converting integer value 1 to f32.

UGQRx[LD_SCALE] Scaling Factor (S) Result
100000 -32 4.29 E+9
100001 -31 2.15 E+9
...
111110 -2 4.00 E+0
111111 -1 2.00 E+0
000000 0 1.00 E+0
000001 1 5.00 E-1
...
011111 31 4.66 E-10

The ST_SCALE field of the UGQR is only used when storing an integer type.

Table converting 100.0 floating-point value to integer values, result = ROUND(F * 2S).

UGQRx[ST_SCALE] Scaling Factor (S) u8 u16 s8 s16
100000 -32 0 0 0 0
100001 -31 0 0 0 0
...
111110 -2 25 25 25 25
111111 -1 50 50 50 50
000000 0 100 100 100 100
000001 1 200 200 127 200
000010 2 255 400 127 400
...
011111 31 255 65535 127 32767

Behavior of __PSQ_L, __PSQ_LX, and __PSQ_ST, __PSQ_STX

#include <ppc_ghs.h>

f32x2 in[10];
u8 in_u8[10];

f32x2 out[10];
u8 out_u8[10];

f32x2   ps0;
f32x2   ps1;
f32x2   ps2;
f32x2   ps3;
f32x2   ps4;
f32x2   ps5;
f32x2   ps6;
f32x2   ps7;

...

__MTSPR(UGQR7, 0x02040204); /* read u8 scale by 0.25, write u8 scale by 4 */

ps0 = __PSQ_L (&in[0],     0, 0);
ps1 = __PSQ_LX(&in[0],  8, 0, 0);
ps2 = __PSQ_L (&in[2],     1, 0);
ps3 = __PSQ_LX(&in[0], 24, 1, 0);

ps4 = __PSQ_L (&in_u8[0],      0, 7);
ps5 = __PSQ_LX(&in_u8[0],   8, 0, 7);
ps6 = __PSQ_L (&in_u8[2],      0, 7);
ps7 = __PSQ_LX(&in_u8[0],  24, 0, 7);

__PSQ_ST (&out[0],     ps0, 0, 0);
__PSQ_STX(&out[0],  8, ps1, 0, 0);
__PSQ_ST (&out[2],     ps2, 1, 0);
__PSQ_STX(&out[0], 24, ps3, 1, 0);

__PSQ_ST (&out_u8[0],      ps4, 0, 7);
__PSQ_STX(&out_u8[0],   8, ps5, 0, 7);
__PSQ_ST (&out_u8[2],      ps6, 0, 7);
__PSQ_STX(&out_u8[0],  24, ps7, 0, 7);

Is equivalent to:

ps0[0] = in[0][0];
ps0[1] = in[0][1];

ps1[0] = in[1][0];
ps1[1] = in[1][1];

ps2[0] = in[2][0];
ps2[1] = 1.0;

ps3[0] = in[3][0];
ps3[1] = 1.0;

ps4[0] = 0.25 * (float) in_u8[0][0];
ps4[1] = 0.25 * (float) in_u8[0][1];

ps5[0] = 0.25 * (float) in_u8[1][0];
ps5[1] = 0.25 * (float) in_u8[1][1];

ps6[0] = 0.25 * (float) in[2][0];
ps6[1] = 1.0;

ps7[0] = 0.25 * (float) in[3][0];
ps7[1] = 1.0;

out[0][0] = ps0[0];
out[0][1] = ps0[1];

out[1][0] = ps1[0];
out[1][1] = ps1[1];

out[2][0] = ps2[0];
/* out[2][1] is unchanged */

out[3][0] = ps3[0];
/* out[3][1] is unchanged */

out_u8[0][0] = (u8) ROUND(ps4[0] * 4.0);
out_u8[0][1] = (u8) ROUND(ps4[1] * 4.0);

out_u8[1][0] = (u8) ROUND(ps5[0] * 4.0);
out_u8[1][1] = (u8) ROUND(ps5[1] * 4.0);

out_u8[2][0] = (u8) ROUND(ps6[0] * 4.0);
/* out_u8[2][1] is unchanged */

out_u8[3][0] = (u8) ROUND(ps7[0] * 4.0);
/* out_u8[3][1] is unchanged */

Do Not Call From

__PSQ_L

None.

__PSQ_LX

None.

__PSQ_ST

None.

__PSQ_STX

None.

See Also

Paired Single Type

Paired Single Functions

__PS_ABS
__PS_ADD
__PS_ADDS
__PS_FDUP
__PS_DIV
__PS_DIVS
__PS_MADD
__PS_MADDS
__PS_MADDS0
__PS_MADDS1
__PS_MERGE00
__PS_MERGE01
__PS_MERGE10
__PS_MERGE11
__PS_MSUB
__PS_MSUBS
__PS_MUL
__PS_MULS
__PS_MULS0
__PS_MULS1
__PS_NABS
__PS_NMADD
__PS_NMADDS
__PS_NMSUB
__PS_NMSUBS
__PS_NEG
__PS_NEGS
__PS_RES
__PS_RESS
__PS_RSQRTE
__PS_SEL
__PS_SUB
__PS_SUM0
__PS_SUM1
__PS_SUBS

Fast Cast Routines

OSInitFastCast
OSf32tos16
OSf32tos8
OSf32tou16
OSf32tou8
OSs16tof32
OSs8tof32
OSu16tof32
OSu8tof32

Revision History

2013/05/08 Automated cleanup pass.
2011/09/21 Initial version.


CONFIDENTIAL