lb and lbu commands accepts 16-bit signed offsets. But GAS accepts larger offsets for these commands. If an offset does not fit in 16-bit range, lb command is translated into lui/lb or lui/addu/lb series. It's interesting that initially LLVM assembler supported this feature, but later it was broken.
This patch restores support for 32-bit offsets. It replaces mem_simm16 operand for LB and LBu definitions by the mem operand and checks the offset's range in the MipsAsmParser::expandLoadInst routine.
Some issues remain:
- If lb / lbu instructions use out-of-range offset, assembler shows an error. But in the MipsAsmParser::expandLoadInst routine assembler does not know about position of invalid instruction's operand and uses beginning of a whole instruction as a point of error. There is an alternative patch D45020 which uses another approach for the range checking and shows a place of the error more precisely.
- The regression also affects LD, SD, LH, LHU commands. I'm going to fix them by a separate patch.
- GAS accepts any 32-bit values as an offset. Now LLVM accepts signed 16-bit values and this patch extends the range to signed 32-bit offsets. In other words, the following code accepted by GAS and still triggers an error by LLVM:
lb $4, 0x80000004 # gas lui a0, 0x8000 lb a0, 4(a0)
- In case of 64-bit pointers GAS accepts a 64-bit offset and translates it to the li/dsll/lb series of commands. LLVM still rejects it. Probably this feature has never been implemented in LVVM. This issue is for a separate patch.
lb $4, 0x800000001 # gas li a0, 0x8000 dsll a0, a0, 0x14 lb a0, 4(a0)