PowerPC: lift more instructions, model reservations and barriers, fix decoding and lifting bugs - #8379
Open
Marvisak wants to merge 8 commits into
Open
PowerPC: lift more instructions, model reservations and barriers, fix decoding and lifting bugs#8379Marvisak wants to merge 8 commits into
Marvisak wants to merge 8 commits into
Conversation
- stdu/ldu never updated rA (guards checked the wrong instruction ID) - lbzux/lhzux/lhaux/lwzux updates were no-ops (rA = rA instead of rA + rB) - lbzu passed the address size into operToIL's options parameter - ld/ldu/ldx/ldux/ldarx/stdx/stdux read registers at 4 bytes, truncating addresses (and stdx's stored value) to 32 bits on ppc64 - load_float used hardcoded 32-bit address math and update writes - trap lifting now emits a nop for the TO=0 never-trap form and guards operand counts
- trap: the canonical unconditional trap encoding (tw 31,0,0) now lifts to a trap instead of unimplemented - lnia/addpcis: PC materialization lifts to the actual address constant - lbarx/lharx and stbcx./sthcx.: byte/halfword reservation forms wired into the existing load-reserve/store-conditional modeling - lfdx/lfdu/lfdux and stfsu/stfsux/stfdx/stfdu/stfdux: double/update FP load and store forms, matching the existing lfs/stfs conventions - ldbrx/stdbrx: byte-reversed doubleword accesses (ByteReverseRegister generalized to 8-byte operations) - rfid/hrfid/rfci/rfdi/rfmci/rfebb: lifted as returns like rfi so blocks terminate properly in kernel/firmware code - xnop lifts to a nop Also fixes in this area: load_float compared the base register against 0 instead of PPC_REG_GPR0 (lfs/lfd with rA=0 read r0 instead of using 0), its X-form path produced invalid IL for rA=0, and stfs/stfsx/stfd computed addresses with 4-byte math on ppc64.
- fsqrt/fsqrts -> FloatSqrt; frin/friz/frip/frim -> RoundToInt/ FloatTrunc/Ceil/Floor - fctiw[u][z]/fctid[u][z] -> FloatToInt and fcfid[u][s] -> IntToFloat (LLIL has no unsigned or rounding-mode-aware conversions, so u/z variants map to the signed conversion) - fsel lifted as a compare-and-select, fcpsgn as sign/magnitude bit ops - lfiwax/lfiwzx/stfiwx integer-word FPR accesses - extswsli, divwe/divweu (widened 64-bit divide) and divde/divdeu (double-precision divide) - lswi/stswi unrolled into word/byte loads and stores at lift time - setb from the CR field's LT/GT flags Replaces the previous fctiwz lifting, which never converted to an integer (FloatTrunc is a float->float rounding), read the double at 4 bytes, and left the result in the wrong half of the register due to an IBM bit-numbering mix-up.
- cmpeqb: EQ of the target CR field set from an OR of the 8 byte compares; cmprb: EQ from the range check(s) of rA's low byte against the bounds in rB, honoring the L operand - mfocrf: builds the selected CR field's bits in their CR positions; mtocrf: shares the mtcrf lifting (same per-field flag writes) - mtocrf's decoded operand order was rS, FXM - reversed from mtcrf, the assembler's grammar (mtocrf NUM, GPR), and the ISA syntax; now decodes as FXM, rS
Follows the __set_reservation/__check_reservation pattern: - memory barriers: sync/lwsync/ptesync/eieio/isync/mbar - cache maintenance with visible effects: dcbz/dcbzl (block zeroing), dcbf/dcbst/dcbi/icbi, all taking the effective address; pure hints (dcbt/dcbtt/dcbtst/dcbtstt/dcba) lift to nops - bit operations without LLIL equivalents: popcntb/popcntw/popcntd, cmpb, bpermd, darn - time base reads: mftb/mftbu - MSR/SPR access: mfmsr and mfspr upgraded from "rD = unimplemented" placeholders to intrinsics; mtmsr/mtmsrd and mtspr newly lifted - FPSCR access: mffs/mtfsf/mtfsb0/mtfsb1 mfxer/mtxer are lifted in pure IL instead, assembling and splitting the modeled SO/OV/CA flags at their XER bit positions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A batch of PowerPC improvements: fills in lifting for a large number of instructions the decoder already recognized but that were dropped on the floor at the IL layer, models the load-and-reserve / store-conditional pair properly, adds intrinsic modeling for barriers and system instructions, and fixes a series of decoding and lifting bugs found along the way — including several that corrupted address dataflow on ppc64.
Decoder fixes
mtmsr/mtmsrd— the optionalLbit sits in the low bit of theRAfield slot, but the decoder required the entire field to be zero, somtmsrd rS, 1decoded as invalid. The check now masks off theLbit (a & 0x1e), andLis emitted as aUIMMoperand when set, so bothmtmsrd rSandmtmsrd rS, 1disassemble.mtocrf— decoded its operands asrS, FXM, reversed frommtcrf, the assembler's own grammar (mtocrf NUM, GPR), and the ISA syntax, so round-tripping assembly through the disassembler was broken. It now decodes asFXM, rS.Reservation / atomics modeling
stwcx.was previously lifted as a plain unconditional store and never touchedCR0, andlwarx/ldarx/stdcx.had no lifting at all. Two new intrinsics —__set_reservationand__check_reservation— model the reservation:lwarx/ldarx/lbarx/lharxemit__set_reservation(ea)after the load.stwcx./stdcx./stbcx./sthcx.branch on__check_reservation(ea): on success the store is performed andCR0is set to0b00 || 1 || XER[SO]; on failure no store happens andCR0reports failure.This mirrors how the existing MIPS (
ll/sc) and ARMv7/AArch64 (ldrex/strex) lifters model store-conditional, so the resulting IL should look familiar.Newly lifted instructions
Integer
cntlzw[.]was lifted through a__builtin_clzintrinsic; it now uses the nativeCountLeadingZerosIL op, andcntlzd[.],cnttzw[.],cnttzd[.]are lifted the same way. All four honor theRcbit and writeCR0.lwa,lwax,lwaux(load 4 bytes, sign-extend into the destination register;lwauxupdatesrA).mulld[.],mulhd[.],mulhdu[.],divd[.],divdu[.].divwe[.]/divweu[.]as widened 64-bit divides ofrA << 32, anddivde[.]/divdeu[.]via double-precision division of a 128-bit dividend.modsw,moduw,modsd,modud.extswsli[.],setb(computed branchlessly asGT - LTof the CR field's flags), andcmpeqb/cmprb(P9 byte compares, setting the target CR field'sEQfrom the byte match / range check).lnia/addpcislift to the actual next-instruction-address constant, which unlocks downstream analysis of position-independent code.ldbrx/stdbrx(the byte-reverse helper is generalized to 8-byte operations).lswi/stswiare unrolled at lift time: the byte count is an immediate, so full words become word loads/stores (with register wraparound pastr31) and the final partial register becomes explicit byte accesses, left-justified per the ISA.mfocrf/mtocrf(single-field variants of the already-liftedmfcr/mtcrf).Traps
Previously only
twuwas lifted (as an unconditional trap). Now the fullTOfield is decoded fortd/tw/tdi/twiand all of their extended mnemonics (tdeq,twlgt,twllei, …), producing anIfon the corresponding comparison guarding theTrap. ArbitraryTOvalues on the generic forms fall back to OR-ing together the enabled comparisons;TO == 0lifts to a nop andTO == 0x1fto an unconditional trap. The canonicaltrapencoding (tw 31,0,0) — what compilers emit for__builtin_trapand assertion failures — gets its own decoder ID and is now covered too.Floating point
fctiw[u][z.],fctid[u][z.]→FloatToInt;fcfid[u][s.]→IntToFloat. (LLIL has no unsigned or rounding-mode-aware conversion ops, so theu/zvariants map to the signed conversion.)frin/friz/frip/frim→RoundToInt/FloatTrunc/Ceil/Floor.fsqrt[s.],fsel(compare-against-zero select),fcpsgn(sign/magnitude bit ops).lfiwax,lfiwzx,stfiwx.lfdx/lfdu/lfduxandstfsu/stfsux/stfdx/stfdu/stfdux, matching the existinglfs/stfsconventions.Control flow / misc
rfid,hrfid,rfci,rfdi,rfmci,rfebblift as returns likerfi, so blocks terminate properly in kernel/firmware code.xnoplifts as a nop.System and barrier instructions as intrinsics
Following the
__set_reservationpattern:sync,lwsync,ptesync,eieio,isync,mbar→__sync,__lwsync, ….dcbz/dcbzl(block zeroing),dcbf,dcbst,dcbi,icbi, each taking the computed effective address. Pure placement hints (dcbt,dcbtt,dcbtst,dcbtstt,dcba) lift to nops.popcntb/popcntw/popcntd,cmpb,bpermd,darn.mftb/mftbu.mfmsrandmfsprupgraded fromrD = unimplementedplaceholders to__mfmsr()/__mfspr(spr);mtmsr/mtmsrdandmtsprnewly lifted as their write counterparts.mffs,mtfsf,mtfsb0,mtfsb1.mfxer/mtxerare lifted in pure IL instead: since SO/OV/CA are already modeled as flags, they're assembled into / split out of their XER bit positions directly.Lifting bug fixes
stdunever updatedrA— the update branch tested forPPC_ID_STWU, which can't reach that case. Sincestdu r1, -N(r1)is the standard ppc64 prologue, this broke stack-pointer tracking for essentially every 64-bit function.lduhad the identical bug (testedPPC_ID_LWZU).lduxnever updatedrA— same dead-guard pattern (testedPPC_ID_LWZUX), and it also computed the wrong value, writing backrAinstead ofrA + rB.lbzux/lhzux/lhaux/lwzuxupdates were no-ops — for these X-form loads the "update" emittedrA = rA; they now writerA = rA + rB.lbzupassed the address size intooperToIL'soptionsparameter instead of the register-size parameter, computing the update at 4 bytes on ppc64.ld/stdfamily —ld/ldu/ldx/ldux/ldarx/stdx/stduxread their base/index registers at 4 bytes (theoperToILdefault), computing every address in 32-bit math on ppc64;stdxalso read the stored value at 4 bytes.stfs/stfsx/stfdhad the same 4-byte address math.load_floathardcoded 32-bit address math and update writes (wrong on ppc64), compared the base register against0instead ofPPC_REG_GPR0(solfs/lfdwithrA=0readr0instead of using literal zero), and produced invalid IL for X-form loads withrA=0.fctiwzhad a broken lifting: it "converted" withFloatTrunc(a float→float rounding, so no integer ever materialized), read the double at 4 bytes, and left the result in the wrong half of the register due to an IBM bit-numbering mix-up. It now goes through the same conversion path as the rest of thefcti*family.Notes
The
PPCIntrinsicenum has been renumbered (theCNTLZWintrinsic was removed and the reservation/barrier/system intrinsics added). Databases saved with the old numbering may display stale intrinsic names for the paired-single intrinsics; fresh analysis is unaffected.