This is an archive of the discontinued LLVM Phabricator instance.

[mips][microMIPS] Implement LWP and SWP instructions
ClosedPublic

Authored by zbuljan on Jun 23 2015, 2:29 AM.

Details

Summary

The patch implements microMIPSr6 LWXS, LWP and SWP instructions.

Diff Detail

Event Timeline

zbuljan updated this revision to Diff 28209.Jun 23 2015, 2:29 AM
zbuljan retitled this revision from to [mips][microMIPS] Implement LWXS, LWP and SWP instructions.
zbuljan updated this object.
zbuljan edited the test plan for this revision. (Show Details)
zbuljan added subscribers: petarj, Unknown Object (MLST).
dsanders requested changes to this revision.Jun 23 2015, 5:53 AM
dsanders edited edge metadata.
dsanders added inline comments.
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
4120–4125

While this looks like a sensible thing to do I'm afraid this isn't correct. The problems it causes will be very subtle and might not reveal themselves for a long time. It's not a parse failure to let non-GPR's through here, we just have to catch them during matching using predicates instead.

The root of the problem is that all parsing decisions are final since there is no backtracking. Making matching decisions during the parse can can cause erratic behaviour that depends on the order of the matcher table. About a year ago, this became apparent when the parser was selecting FPU register classes at parse time. As a result, the matcher was failing to match legitimate code because the parser had made the wrong decision, blocking the possibility of matching the correct instruction. This is also why numeric registers aren't resolved to a register class until the moment they are rendered into an instruction. If we decided earlier, then an incorrect decision would prevent the assembler matching valid instructions.

lib/Target/Mips/Disassembler/MipsDisassembler.cpp
1446–1448

Nit: LLVM convention is operators on the previous line like so:

if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM ||
    Inst.getOpcode() == Mips::LWP_MMR6 || Inst.getOpcode() == Mips::SWP_MMR6)
lib/Target/Mips/MicroMips32r6InstrFormats.td
366–368

Please extract the two pieces of addr to separate fields as per CACHE_PREF_FM_MM. It serves to explain the unusual encoding.

lib/Target/Mips/MicroMips32r6InstrInfo.td
371–382

LWXS was removed in microMIPSr6

384–413

Possible Nit: There's no need for a separate *_DESC_BASE if there's only one *_DESC inheriting from it. Are there more instructions on the way that will use these *_DESC_BASE's?

This revision now requires changes to proceed.Jun 23 2015, 5:53 AM
zbuljan updated this revision to Diff 29878.Jul 16 2015, 3:53 AM
zbuljan edited edge metadata.

Used predicate method for regpair operand check instead of additional lines of code in parseRegisterPair method.
Extracted two pieces of addr to separate fields in LWM_FM_MMR6 class.
Removed implementation of LWXS instruction.
Removed separate _DESC_BASE classes.

zoran.jovanovic retitled this revision from [mips][microMIPS] Implement LWXS, LWP and SWP instructions to [mips][microMIPS] Implement LWP and SWP instructions.Aug 4 2015, 2:16 AM
zoran.jovanovic edited edge metadata.
dsanders requested changes to this revision.Sep 14 2015, 7:06 AM
dsanders edited edge metadata.
dsanders added inline comments.
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
974

LLVM convention is operators on the previous line

1036

You want to test RegIdxOp::Index rather than ParsedRegNum (0-31 contains NoRegister, DSPCCond, MSACSR, and AT_64, among others).

Also, I think it should be '30' instead of '31' since register pairs consist of Index and Index+1

4120–4125

This update is closer and fixes the subtle bugs but is still making the key mistake described in my previous comment. You're trying to convert to a internal register number too early.

You need to remove RegIdxOp::ParsedRegNum and the related changes and leave the conversion to an internal register number to the render method (addRegPairOperand()). The reason this render method doesn't work at the moment is that it's trying to use an index as a register number. It's missing the call to getGPR32Reg() that other renderers like addGPR32AsmRegOperands() have.

lib/Target/Mips/Disassembler/MipsDisassembler.cpp
1446–1448

This hasn't been fixed.

lib/Target/Mips/MicroMips32r6InstrFormats.td
366–368

Done

lib/Target/Mips/MicroMips32r6InstrInfo.td
371–382

Done

384–413

Done

This revision now requires changes to proceed.Sep 14 2015, 7:06 AM
zbuljan updated this revision to Diff 35840.Sep 28 2015, 1:50 AM
zbuljan edited edge metadata.

Removed RegIdxOp::ParsedRegNum.
Added test to RegIdxOp::Index in isRegPair() method.
Conversion to an internal register number is placed in addRegPairOperands() method.

zbuljan updated this revision to Diff 40494.Nov 18 2015, 4:47 AM
zbuljan edited edge metadata.

Rebased to work with top of the tree.

zbuljan updated this revision to Diff 50415.Mar 11 2016, 3:53 AM

Rebased to work with top of the tree.

sdardis edited edge metadata.Apr 19 2016, 7:42 AM

This patch looks mostly correct to me except it's missing a key issue, that for lwp rd and base cannot be the same. lwp is not guaranteed to be uninterruptible so an interrupt could render lwp not restartable if they are the same.

Fortunately we already have an similar example with jalr.hb. You need to extend MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) on line 3668 to account for this context sensitive predicate.

sdardis accepted this revision.Apr 19 2016, 7:42 AM
sdardis requested changes to this revision.
sdardis edited edge metadata.
sdardis edited edge metadata.

Argh, misclicked.

This revision now requires changes to proceed.Apr 19 2016, 7:43 AM
zbuljan updated this revision to Diff 55537.Apr 29 2016, 12:40 AM
zbuljan edited edge metadata.

Rebased to work with TOT.
Added check for Rd and Base registers of LWP to MipsAsmParser::checkTargetMatchPredicate method.
Added invalid test for the case of same Rd and Base registers of LWP instruction.
Renamed mem_simm12gpr to mem_simm12 and added DiagnosticType "MemSImm12" to MipsMemSimm12AsmOperand class.
Added selection of proper register class (32/64-bit) to addRegPairOperands method (MipsAsmParser.cpp).

sdardis accepted this revision.May 6 2016, 5:23 AM
sdardis edited edge metadata.

LGTM, for the error messages that are incorrect, can you copy the FIXME I've mentioned in inline comments?

test/MC/Mips/micromips/invalid.s
61 ↗(On Diff #55537)

This is a wrong error message. 8 falls within the range of a 12-bit signed offset. Can you copy the FIXME from micromips32r6/invalid.s below swe here?

test/MC/Mips/micromips32r6/invalid.s
54–58

See my comment above.

test/MC/Mips/micromips64r6/invalid.s
60

See my comment above about the wrong error message.

This revision was automatically updated to reflect the committed changes.