A shift feeding an OR
Chaining bitwise work means the result of one operation immediately becomes fuel for the next. The bread-and-butter version goes like this: you slide a value left to open up some room, then OR a second value down into the bits you just cleared.
make_word(hi, lo) is a fine example. It pushes the high part up by 16 and drops the low part in underneath it.
slwi r0,r3,16
or r3,r0,r4
blr
The first line, slwi r0, r3, 16, is shift-left-word-immediate. Every bit of r3 climbs 16 places and the result parks in r0, which leaves the bottom 16 bits of r0 sitting at zero. There's your gap. Now or r3, r0, r4 fills it straight from r4, because any bit set in either operand still shows up in r3.
Two instructions, sure, but one idea. The slwi output only has to stay alive for a single cycle before or eats it.
Your target unpacks the same way: the slwi amount is how far the high value travels, and the two or operands tell you which register is carrying which half, which between them is enough to write the C.
Your task
Write pack_shift_or, taking two ints, to reproduce the assembly above.