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);