4. Data Movement and Conversion#
4.1. addrcast#
Convert between specific and generic address spaces.
Convert from specific address space to generic address space:
addrcast.to.from dst, src0 .to = { .generic } .from = { .private, .shared, .global, .const } - dst is a 64-bit register - src0 can be a register or memory variable
Restrictions
bitwidth of
src0must match the address size of.fromaddress space of
src0must match value of.from
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Convert from generic address space to specific address space:
addrcast.to.from dst, src0 .to = { .global, .private, .shared } .from = { .generic } - dst is a register - src0 is a 64-bit register
Restrictions
bitwidth of
dstmust match the address size of.to
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Notes:
The representation of generic address values is implementation-defined. However, casting an address from a specific address space to the generic address space and then casting it back to the original address space is guaranteed to preserve the value. Pointer arithmetic on the generic address behaves the same as on the original specific address, as long as the result stays in bounds.
Note
Casting a generic address in the .const address space must use addrcast.global.generic.
Warning
Behavior is undefined if the address space of src0 does not match the .from qualifier.
.reg .32b %paddr;
.reg .64b %gaddr;
.private .align 4 @A[8];
// convert generic address to private
addrcast.private.generic %paddr, %gaddr;
// convert private address to generic
addrcast.generic.private %gaddr, %paddr;
// convert private variable address to generic
addrcast.generic.private %gaddr, @A;
4.2. addrof#
Compute the non-generic address of a source variable.
Address of a memory variable:
addrof.type dst, src0 .type = { .32b, .64b } - dst is a register - src0 is a memory variable
Restrictions
bitwidth of
dstmust match the bitwidth of.typeaddress size of storage space of
src0must match the bitwidth of.type
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Address of a function:
addrof.type dst, src0 .type = { .64b } - dst is a 64-bit register - src0 is a function name
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst = &src0
Examples:
.import .function void @foo();
.reg .32b %dst;
.reg .64b %dst64;
.private @A[10];
.global @B[4];
// get 32-bit address of private variable
addrof.32b %dst, @A;
// get 64-bit address of global variable
addrof.64b %dst64, @B;
// get 64-bit address of function
addrof.64b %dst64, @foo;
4.3. extract.dynamic#
Extract an element from a vector register using a dynamic index.
Syntax:
extract.dynamic.vec.type dst, src0, index .vec = { .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v16, .v32, .v64 } .type = { .32b } - dst, index are 32-bit registers - src0 is a 32-bit element vector register
Restrictions
number of elements of
src0must match value of.vec
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst = src0[index]
Notes:
Warning
Behavior is undefined if the index is out of bounds for src0.
Examples:
.reg .v4.32b %src0;
.reg .32b %dst, %index;
// extract single element from %src0 at %index
extract.dynamic.v4.32b %dst, %src0, %index;
4.4. extract#
Extract elements from a vector register.
Extract scalar from vector register:
extract.index.type dst, src0 .index = { .0, ..., .63 } .type = { .32b } - dst is a 32-bit register - src0 is a 32-bit element vector register
Restrictions
value of
.indexmust be less than the number of elements insrc0
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Extract subvector from vector register:
extract.index.vec.type dst, src0 .index = { .0, ..., .63 } .vec = { .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v16, .v32, .v64 } .type = { .32b } - dst, src0 are 32-bit element vector registers
Restrictions
number of elements of
dstmust match value of.vecqualifier
.indexmust be aligned to the number of elements indstsum of value of
.indexand number of elements indstmust not exceed the number of elements insrc0
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
for (i = 0; i < element_count(dst); i++) {
dst[i] = src0[index + i]
}
Notes:
It is illegal to specify swizzle for dst or src0.
Examples:
.reg .v4.32b %src0;
.reg .32b %dst;
.reg .v2.32b %dstVec;
// extract single element from %src0 at index 1
extract.1.32b %dst, %src0;
// extract 2 elements from %src0 at index 2
extract.2.v2.32b %dstVec, %src0;
4.5. f2i#
Convert a floating-point value to an integer.
Syntax:
f2i.to.from<.rndmode> dst, src0 .to = { .u8, .s8, .u16, .s16, .u32, .s32, .u64, .s64 } .from = { .bf, .hf, .f, .df } .rndmode = { .re, .rd, .ru, .rz, .rna } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstmust match the bitwidth of.tobitwidth of
src0must match the bitwidth of.from
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
rnd = round(src0, .rndmode)
dst = type_convert(rnd, .to)
Notes:
If the resulting value (post-rounding) exceeds the range that can be represented by the integer type, the conversion result is clamped to the largest/smallest representable value. The conversion rules are summarized below, where Imax is the largest representable value by the integer type while Imin is the smallest representable value by the same type.
|
|
Floating-point Exception |
|---|---|---|
qNaN |
0 |
Invalid Operation |
sNaN |
0 |
Invalid Operation |
+inf |
Imax |
Invalid Operation |
f > Imax |
Imax |
Invalid Operation |
Imin <= f <= Imax |
in-range, representable signed integer i |
Inexact if rounding changes f |
f < Imin |
Imin |
Invalid Operation |
-inf |
Imin |
Invalid Operation |
|
|
Floating-point Exception |
|---|---|---|
qNaN |
0 |
Invalid Operation |
sNaN |
0 |
Invalid Operation |
+inf |
Imax |
Invalid Operation |
f > Imax |
Imax |
Invalid Operation |
0 <= f <= Imax |
in-range, representable unsigned integer i |
Inexact if rounding changes f |
-0 |
0 |
None |
-1 < f < 0 |
0 |
Inexact if rounded result is zero Invalid Operation if result is -1 |
-fmax <= f <= -1 |
0 |
Invalid Operation |
-inf |
0 |
Invalid Operation |
Examples:
.reg .32b %dst, %src0;
// convert single-precision to signed 32bit integer
f2i.s32.f %dst, %src0;
// convert single-precision to unsigned 32-bit integer with round-up rounding
f2i.u32.f.ru %dst, %src0;
4.6. fext#
Extend a floating-point value to higher precision.
Syntax:
fext.to.from dst, src0 .to = { .f, .df } .from = { .bf, .hf, .f } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstmust match the bitwidth of.tobitwidth of
src0must match the bitwidth of.frombitwidth of
.tomust be greater than the bitwidth of.from
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
default#dst = type_convert(src0, .to)
Notes:
Source Floating Point Value (hf, bf, f) |
Destination Floating Point Result (f, df) |
|---|---|
-inf |
-inf |
-finite |
-finite |
-denorm |
-finite |
-0 |
-0 |
+0 |
+0 |
+denorm |
+finite |
+finite |
+finite |
+inf |
+inf |
NaN |
NaN |
Examples:
.reg .32b %dst;
.reg .16b %src0;
// convert half-precision float to single-precision float
fext.f.hf %dst, %src0;
4.7. frnd#
Round a floating-point number to the nearest integer.
Syntax:
frnd.rndmode<.ftz>.type dst, src0 .rndmode = { .re, .rd, .ru, .rz, .rna } .type = { .bf, .hf, .f, .df } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstandsrc0must match the bitwidth of.type
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst = round(src0, .rndmode)
Examples:
.reg .32b %dst, %src0;
// round-to-even of single-precision element
frnd.re.f %dst, %src0;
4.8. ftrunc#
Truncate a floating-point value to lower precision.
Syntax:
ftrunc.to.from<.rndmode><.ftz><.dsat> dst, src0 .to = { .bf, .hf, .f } .from = { .f, .df } .rndmode = { .re, .rd, .ru, .rz, .rna } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstmust match the bitwidth of.tobitwidth of
src0must match the bitwidth of.frombitwidth of
.tomust be less than the bitwidth of.from
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
default#dst = truncate(src0, .to)
Notes:
Enabling saturation via .dsat qualifier clamps the final result to between
the min/max float values representable by .to type. When .dsat is not specified:
if source > maximum value of destination type, destination is set to +infinity
if source < minimum value of destination type, destination is set to -infinity
Source Floating Point Value (f, df) |
Destination Floating Point Result (hf, bf, f) |
|---|---|
-inf |
-inf |
-finite |
-finite/-denorm/-0 |
-denorm |
-0 |
-0 |
-0 |
+0 |
+0 |
+denorm |
+0 |
+finite |
+finite/+denorm/+0 |
+inf |
+inf |
NaN |
NaN |
Examples:
.reg .32b %src0;
.reg .16b %dst;
// convert single-precision float to half-precision float
ftrunc.hf.f %dst, %src0;
// convert single-precision float to half-precision float with rounding
ftrunc.hf.f.ru %dst, %src0;
4.9. ftrunc2#
Truncate and pack two floating-point values into a packed vector.
Syntax:
ftrunc2.to<.rndmode><.ftz><.dsat> dst, src0, src1 .to = { .bfx2, .hfx2 } .rndmode = { .re, .rd, .ru, .rz, .rna } - dst is a 2x16-bit vector register - src0, src1 are 32-bit registers
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
.to == .hfx2#ftrunc.hf.f dst[15:0], src0
ftrunc.hf.f dst[31:16], src1
.to == .bfx2#ftrunc.bf.f dst[15:0], src0
ftrunc.bf.f dst[31:16], src1
Notes:
Enabling saturation via .dsat qualifier clamps the final result to between
the min/max float values representable by .to type. When .dsat is not specified:
if source > maximum value of destination type, destination is set to +infinity
if source < minimum value of destination type, destination is set to -infinity
Examples:
.reg .32b %dst, %src0, %src1;
// truncate and pack 2 single-precision elements (dst must be .v2.16b)
.reg .v2.16b %dst_packed;
ftrunc2.hfx2 %dst_packed, %src0, %src1;
4.10. i2f#
Convert an integer to a floating-point value.
Syntax:
i2f.to.from<.rndmode><.dsat> dst, src0 .to = { .bf, .hf, .f, .df } .from = { .u8, .s8, .u16, .s16, .u32, .s32, .u64, .s64 } .rndmode = { .re, .rd, .ru, .rz, .rna } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstmust match the bitwidth of.tobitwidth of
src0must match the bitwidth of.from
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst = type_convert(src0, .to)
Notes:
Enabling saturation via .dsat qualifier clamps the final result to between
the min/max float values representable by .to type. When .dsat is not specified:
if source > maximum value of destination type, destination is set to +infinity
if source < minimum value of destination type, destination is set to -infinity
Examples:
.reg .16b %dst16, %src16;
.reg .32b %dst32, %src32;
.reg .64b %dst64, %src64;
// convert unsigned short to half-precision floating-point with implicit .re rounding
i2f.hf.u16 %dst16, %src16;
// convert signed short to single-precision floating-point with explicit rounding
i2f.f.s16.rd %dst32, %src16;
// convert signed int to double-precision floating-point with explicit rounding and saturation
i2f.df.s32.rz.dsat %dst64, %src32;
4.11. insert.dynamic#
Insert an element into a vector using a dynamic index.
Syntax:
insert.dynamic.vec.type dst, src0, index .vec = { .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v16, .v32, .v64 } .type = { .32b } - dst is a 32-bit element vector register - src0, index are 32-bit registers
Restrictions
number of elements of
dstmust match value of.vec
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst[index] = src0
Notes:
Warning
Behavior is undefined if the index is out of bounds for dst.
Examples:
.reg .v4.32b %dst;
.reg .32b %src0, %index;
// insert single element at %index
insert.dynamic.v4.32b %dst, %src0, %index;
4.12. insert#
Insert elements into a vector.
Insert scalar into vector register:
insert.index.type dst, src0 .index = { .0, ..., .63 } .type = { .32b } - dst is a 32-bit element vector register - src0 is a 32-bit register
Restrictions
value of
.indexmust be less than the number of elements indst
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Insert subvector into vector register:
insert.index.vec.type dst, src0 .index = { .0, ..., .63 } .vec = { .v2, .v3, .v4, .v5, .v6, .v7, .v8, .v16, .v32, .v64 } .type = { .32b } - dst, src0 are 32-bit element vector registers
Restrictions
number of elements of
src0must match value of.vecqualifier
.indexmust be aligned to the number of elements insrc0sum of value of
.indexand number of elements insrc0must not exceed the number of elements indst
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
for (i = 0; i < element_count(src); i++) {
dst[index + i] = src[i]
}
Notes:
It is illegal to specify swizzle for dst or src0.
Examples:
.reg .v4.32b %dst;
.reg .32b %src0;
.reg .v2.32b %srcVec;
// insert single element from %src0 at index 1
insert.1.32b %dst, %src0;
// insert 2 elements from %srcVec at index 2
insert.2.v2.32b %dst, %srcVec;
4.13. isaddr#
Check if a generic address belongs to a specific address space.
Check if generic address belongs to private/shared/global address space:
isaddr.addrspace dst, src0 .addrspace = { .private, .shared, .global } - dst is a 32-bit register - src0 is a 64-bit register * src0 is interpreted as generic address.
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
if get_address_space(src0) == .addrspace
dst = ~0
else
dst = 0
Examples:
.reg .32b %dst, %src0;
.reg .64b %gen;
// convert private address %src0 to generic address %gen
addrcast.generic.private %gen, %src0;
isaddr.private %dst, %gen; // %r = ~0
isaddr.shared %dst, %gen; // %r = 0
4.14. mov#
Move data between registers.
Scalar to scalar copy:
mov.type dst, src0 .type = { .8b, .16b, .32b, .64b, .128b } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstandsrc0must match the bitwidth of.type
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Scalar to vector copy:
mov.type dst.swizzle, src0 .type = { .8b, .16b, .32b, .64b, .128b } - dst is a vector register - src0 is a register
Restrictions
total width of
dstmust match the bitwidth of.typebitwidth of
src0must match the bitwidth of.type
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Vector to scalar copy:
mov.type dst, src0.swizzle .type = { .8b, .16b, .32b, .64b, .128b } - dst is a register - src0 is a vector register
Restrictions
bitwidth of
dstmust match the bitwidth of.typetotal width of
src0must match the bitwidth of.type
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Vector to vector copy:
mov.type dst.swizzle, src0.swizzle .type = { .8b, .16b, .32b, .64b, .128b } - dst, src0 are vector registers
Restrictions
total width of
dstmust match the bitwidth of.typetotal width of
src0must match the bitwidth of.type
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
// return the start/end bit for reg.swizzle
getSwizzleBits(reg, swizzle) {
w = bitwidth(reg)
switch (swizzle) {
case .x: return {0, w - 1}
case .y: return {w, 2 * w - 1}
case .z: return {2 * w, 3 * w - 1}
case .w: return {3 * w, 4 * w - 1}
case .xy: return {0, 2 * w - 1}
case .zw: return {2 * w, 4 * w - 1}
case .xyzw: return {0, 4 * w - 1}
}
}
dst = src0
[D_S, D_E] = getSwizzleBits(dst, dst_swizzle)
dst[D_S, D_E] = src0
[S_S, S_E] = getSwizzleBits(src, src_swizzle)
dst = src0[S_S, S_E]
[S_S, S_E] = getSwizzleBits(src, src_swizzle)
[D_S, D_E] = getSwizzleBits(dst, dst_swizzle)
dst[D_S, D_E] = src0[S_S, S_E]
Notes:
Number of bits being copied is specified by .type, and must match the
bitwidth of a scalar variable and that of a vector variable after swizzle.
Examples:
.reg .32b %dst, %src0;
.reg .v2.32b %dstVec, %src0Vec;
// scalar to scalar move
mov.32b %dst, %src0;
// scalar to vector move
mov.32b %dstVec.x, %src0;
// vector to scalar move
mov.32b %dst, %src0Vec.y;
// vector to vector move
mov.64b %dstVec.xy, %src0Vec.xy;
4.15. pf2i#
Convert packed floats to packed integers.
Syntax:
pf2i.to.from<.rndmode> dst, src0 .to = { .u16x2, .s16x2 } .from = { .bfx2, .hfx2 } .rndmode = { .re, .rd, .ru, .rz, .rna } - dst, src0 are 2x16-bit vector registers
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst[15:0] = type_convert(src0[15:0], element_type(.to))
dst[31:16] = type_convert(src0[31:16], element_type(.to))
Notes:
Each element independently converted following the rules specified in f2i instruction.
src0 holds a packed floating-point value (.hfx2 or .bfx2) and dst
holds a packed integer value (.u16x2 or .s16x2). Both operands must be
declared as .v2.16b registers (see packed types).
Examples:
.reg .v2.16b %dst_packed, %src_packed;
// conversion using .v2.16b register declarations
pf2i.s16x2.hfx2 %dst_packed, %src_packed;
4.16. sext#
Sign-extend an integer to a larger type.
Syntax:
sext.to.from dst, src0 .to = { .16b, .32b, .64b } .from = { .8b, .16b, .32b } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstmust match the bitwidth of.tobitwidth of
src0must match the bitwidth of.frombitwidth of
.tomust be greater than the bitwidth of.from
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst = sign_extend(src0)
Examples:
.reg .32b %dst;
.reg .16b %src0;
// sign-extend 16-bit element
sext.32b.16b %dst, %src0;
4.17. trunc#
Truncate an integer to a smaller type.
Syntax:
trunc.to.from dst, src0 .to = { .8b, .16b, .32b } .from = { .16b, .32b, .64b } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstmust match the bitwidth of.tobitwidth of
src0must match the bitwidth of.frombitwidth of
.tomust be less than the bitwidth of.from
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst = truncate(src0, .to)
Examples:
.reg .32b %src0;
.reg .16b %dst;
// truncate 32-bit element
trunc.16b.32b %dst, %src0;
4.18. zext#
Zero-extend an integer to a larger type.
Syntax:
zext.to.from dst, src0 .to = { .16b, .32b, .64b } .from = { .8b, .16b, .32b } - dst is a register - src0 can be a register or an immediate
Restrictions
bitwidth of
dstmust match the bitwidth of.tobitwidth of
src0must match the bitwidth of.frombitwidth of
.tomust be greater than the bitwidth of.from
PISA Notes
introduced in PISA version 0.1
requires PISA target 100 or compatible
Semantics:
dst = zero_extend(src0)
Examples:
.reg .32b %dst;
.reg .16b %src0;
// zero-extend 16-bit element
zext.32b.16b %dst, %src0;