Integer Arithmetic Instructions¶
Contents
Common Flags¶
Addition: iadd3¶
iadd3 [mode,x,cc] REG0 [neg,h0/h1] REG1 [neg,h0/h1] REG2 [neg,h0/h1] REG3
iadd3 [x,cc] REG0 [neg] REG1 [neg] CB2 [neg] REG3
iadd3 [x,cc] REG0 [neg] REG1 [neg] S20_2 [neg] REG3
Adds three integers. The flag mode
may optionally be rs
or ls
.
switch (mode) {
case rs:
/* yes, the intermediate addition creates a 33-bit integer */
uint32_t intermediate = (uint33_t(SRC1) + uint33_t(SRC2)) >> 16;
DST = add_with_carry(intermediate, SRC3);
break;
case ls: DST = add_with_carry(((SRC1 + SRC2) << 16), SRC3); break;
default: DST = add_with_carry((SRC1 + SRC2), SRC3); break;
}
Multiply-add: xmad¶
xmad [src1_type,src2_type,psl,mrg,cmode,x,cc] REG0 [h1] REG1 [h1] REG2 REG3
xmad [src1_type,src2_type,cmode,x,cc] REG0 [h1] REG1 [h1] REG2 CB3
xmad [src1_type,src2_type,psl,mrg,cmode,x,cc] REG0 [h1] REG1 [h1] CB2 REG3
xmad [src1_type,src2_type,psl,mrg,cmode,x,cc] REG0 [h1] REG1 S20_2 REG3
Multiplies two 16-bit integers and adds a 32 bit integer, along with a bunch of other stuff.
If one of src1_type
or src2_type
is set, the other must also be set. They can be s16 u16
, u16 s16
or s16 s16
.
The flag cmode
may optionally be clo
, chi
, csfu
or cbcc
. The cbcc
mode may not be specified for the constant buffer forms.
uint32_t p_a = SRC1.h1 ? SRC1>>16 : SRC1&0xffff;
uint32_t p_b = SRC2.h1 ? SRC2>>16 : SRC2&0xffff;
if (src1_type == s16) p_a = sign_extend_from_16_to_32(p_a);
if (src2_type == s16) p_b = sign_extend_from_16_to_32(p_b);
uint32_t p = p_a * p_b;
if (psl) p <<= 16;
uint32_t c = SRC3;
switch (cmode) {
case clo: c = c & 0xffff; break;
case chi: c = c >> 16; break;
case cbcc: c += SRC2 << 16; break;
case csfu: {
if (p_a==0 || p_b==0) break;
//v & 0x80000000 -> as_twos_complement(v) < 0
if (p_a & 0x80000000) c -= 65536;
if (p_b & 0x80000000) c -= 65536;
break;
}
}
DST0 = add_with_carry(p, c);
if (mrg) DST0 = (DST0 & 0xffff) | (SRC2<<16);