Some analysis suggests that all short immediates are sign-extended. The
insnCanLoad logic already accounted for this, but we could still pick
the wrong form when emitting actual instructions that support both short
and long immediates (with the long form usually having additional
restrictions that insnCanLoad should be aware of).
This also reverses a bunch of commits that had previously "worked
around" this issue in various emitters:
9c63224540ef: gm107/ir: make use of ADD32I for all immediates
83a4f28dc27b: gm107/ir: make use of LOP32I for all immediates
b84c97587b4a: gm107/ir: make use of IMUL32I for all immediates
d30768025a22: gk110/ir: make use of IMUL32I for all immediates
as well as the original import for UMUL in the nvc0 emitter.
Reported-by: Karol Herbst <kherbst@redhat.com>
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Tested-by: Karol Herbst <kherbst@redhat.com>
{
const ImmediateValue *imm = ref.get()->asImm();
- return imm && (imm->reg.data.u32 & ((ty == TYPE_F32) ? 0xfff : 0xfff00000));
+ if (ty == TYPE_F32)
+ return imm && imm->reg.data.u32 & 0xfff;
+ else
+ return imm && (imm->reg.data.s32 > 0x7ffff ||
+ imm->reg.data.s32 < -0x80000);
}
void
code[1] |= ((u64 & 0x7fe0000000000000ULL) >> 53);
code[1] |= ((u64 & 0x8000000000000000ULL) >> 36);
} else {
- assert((u32 & 0xfff00000) == 0 || (u32 & 0xfff00000) == 0xfff00000);
+ assert((u32 & 0xfff80000) == 0 || (u32 & 0xfff80000) == 0xfff80000);
code[0] |= (u32 & 0x001ff) << 23;
code[1] |= (u32 & 0x7fe00) >> 9;
code[1] |= (u32 & 0x80000) << 8;
assert(!i->src(0).mod.neg() && !i->src(1).mod.neg());
assert(!i->src(0).mod.abs() && !i->src(1).mod.abs());
- if (i->src(1).getFile() == FILE_IMMEDIATE) {
+ if (isLIMM(i->src(1), TYPE_S32)) {
emitForm_L(i, 0x280, 2, Modifier(0));
if (i->subOp == NV50_IR_SUBOP_MUL_HIGH)
{
if (ref.getFile() == FILE_IMMEDIATE) {
const ImmediateValue *imm = ref.get()->asImm();
- if (isFloatType(insn->sType)) {
- if ((imm->reg.data.u32 & 0x00000fff) != 0x00000000)
- return true;
- } else {
- if ((imm->reg.data.u32 & 0xfff00000) != 0x00000000 &&
- (imm->reg.data.u32 & 0xfff00000) != 0xfff00000)
- return true;
- }
+ if (isFloatType(insn->sType))
+ return imm->reg.data.u32 & 0xfff;
+ else
+ return imm->reg.data.s32 > 0x7ffff || imm->reg.data.s32 < -0x80000;
}
return false;
}
} else if (insn->sType == TYPE_F64) {
assert(!(imm->reg.data.u64 & 0x00000fffffffffffULL));
val = imm->reg.data.u64 >> 44;
+ } else {
+ assert(!(val & 0xfff80000) || (val & 0xfff80000) == 0xfff80000);
}
- assert(!(val & 0xfff00000) || (val & 0xfff00000) == 0xfff00000);
emitField( 56, 1, (val & 0x80000) >> 19);
emitField(pos, len, (val & 0x7ffff));
} else {
break;
}
- if (insn->src(1).getFile() != FILE_IMMEDIATE) {
+ if (!longIMMD(insn->src(1))) {
switch (insn->src(1).getFile()) {
case FILE_GPR:
emitInsn(0x5c400000);
void
CodeEmitterGM107::emitIADD()
{
- if (insn->src(1).getFile() != FILE_IMMEDIATE) {
+ if (!longIMMD(insn->src(1))) {
switch (insn->src(1).getFile()) {
case FILE_GPR:
emitInsn(0x5c100000);
void
CodeEmitterGM107::emitIMUL()
{
- if (insn->src(1).getFile() != FILE_IMMEDIATE) {
+ if (!longIMMD(insn->src(1))) {
switch (insn->src(1).getFile()) {
case FILE_GPR:
emitInsn(0x5c380000);
{
const ImmediateValue *imm = ref.get()->asImm();
- return imm && (imm->reg.data.u32 & ((ty == TYPE_F32) ? 0xfff : 0xfff00000));
+ if (ty == TYPE_F32)
+ return imm && imm->reg.data.u32 & 0xfff;
+ else
+ return imm && (imm->reg.data.s32 > 0x7ffff ||
+ imm->reg.data.s32 < -0x80000);
}
void
} else
if ((code[0] & 0xf) == 0x3 || (code[0] & 0xf) == 4) {
// integer immediate
- assert((u32 & 0xfff00000) == 0 || (u32 & 0xfff00000) == 0xfff00000);
+ assert((u32 & 0xfff80000) == 0 || (u32 & 0xfff80000) == 0xfff80000);
assert(!(code[1] & 0xc000));
u32 &= 0xfffff;
code[0] |= (u32 & 0x3f) << 26;
CodeEmitterNVC0::emitUMUL(const Instruction *i)
{
if (i->encSize == 8) {
- if (i->src(1).getFile() == FILE_IMMEDIATE) {
+ if (isLIMM(i->src(1), TYPE_U32)) {
emitForm_A(i, HEX64(10000000, 00000002));
} else {
emitForm_A(i, HEX64(50000000, 00000003));
assert(!(imm & 0x000fffff));
code[0] = 0x00000318 | imm;
} else {
- assert(imm < 0x800 || ((int32_t)imm >= -0x800));
+ assert(imm < 0x800 && ((int32_t)imm >= -0x800));
code[0] = 0x00000118 | (imm << 20);
}
} else {