Intel 16bit operations with immediate operands in some cases generate 32bit immediate operands rather than 16bit

Description

There's a discrepancy in some of the assembler routines, we generate 32bit immediate operands for some _Word cases and not in others. For example,

// [dstReg + dstDisp] +CF= (word) imm
@Inline(value=Inline.When.ArgumentsAreConstant, arguments={1})
public final void emitADC_RegDisp_Imm_Word(GPR dstReg, Offset disp, int imm) {
int miStart = mi;
setMachineCodes(mi++, (byte) 0x66);
if (fits(imm,8)) {
setMachineCodes(mi++, (byte) 0x83);
// "register 0x2" is really part of the opcode
emitRegDispRegOperands(dstReg, disp, GPR.getForOpcode(0x2));
emitImm8((byte)imm);
} else {
setMachineCodes(mi++, (byte) 0x81);
// "register 0x2" is really part of the opcode
emitRegDispRegOperands(dstReg, disp, GPR.getForOpcode(0x2));
emitImm16(imm);
}
if (lister != null) lister.RDI(miStart, "ADC", dstReg, disp, imm);
}

uses a emitImm16 whereas:

// [dstIndex<<scale + dstDisp] +CF= (word) imm
@Inline(value=Inline.When.ArgumentsAreConstant, arguments={1})
public final void emitADC_RegOff_Imm_Word(GPR dstIndex, short scale, Offset dstDisp, int imm) {
int miStart = mi;
setMachineCodes(mi++, (byte) 0x66);
if (fits(imm,8)) {
setMachineCodes(mi++, (byte) 0x83);
// "register 0x2" is really part of the opcode
emitRegOffRegOperands(dstIndex, scale, dstDisp, GPR.getForOpcode(0x2));
emitImm8((byte)imm);
} else {
setMachineCodes(mi++, (byte) 0x81);
// "register 0x2" is really part of the opcode
emitRegOffRegOperands(dstIndex, scale, dstDisp, GPR.getForOpcode(0x2));
emitImm32(imm);
}
if (lister != null) lister.RFDI(miStart, "ADC", dstIndex, scale, dstDisp, imm);
}

uses a emitImm32. This bug effects 16bit operations with immediates >8bit or any immediate with the test instruction. The broken memory formats are RegOff, Abs and RegIdx.

Environment

None

Assignee

Ian Rogers

Reporter

Ian Rogers

Labels

None

Fix versions

Affects versions

Priority

Medium
Configure