Reputation: 11
Could someone show me an example in C++ of what this PowerPC instruction would look like?
From what I get, we are looking 44 bits shifted to the right inside of r0
, and from there we are extracting the first 8 bits
extrdi r0, r0, 8,44
Upvotes: 1
Views: 296
Reputation: 135
According to PowerPC mnemonics document, extrdi
means extract n bits since bit b, then right-justify it.
Take an 8-bit integer to illustrate:
extrdi r0, r0, 2, 3
r0: A B C D E F G H
| |
+---+
2 2+3-1
After extraction: 0 0 C D E 0 0 0
After justification: 0 0 0 0 0 C D E
We can implement as below (64-bit):
unsigned long extrdi_soft(unsigned long ry, unsigned n, unsigned b) {
unsigned offset = (64 - b - n);
// Generate the n-bit mask beginning from position b
unsigned mask = ((1UL << n) - 1) << offset;
// Do mask and right-justify it
return (ry & mask) >> offset;
}
Compare it against real extrdi
:
unsigned long extrdi_hard(unsigned long rs) {
unsigned long ra = 0;
asm("extrdi %1, %0, 8, 44"
:"=r"(ra)
:"r"(rs));
return ra;
}
// extrdi_hard(0x1234567UL) == extrdi_soft(0x1234567UL, 8, 44)
extrdi rs, ry, n, b
is actually mnemonic to rldicl rs, ry, b+n, 64-n
. The instruction means rotate left then clear left. So we got another way to implement extrdi
:
unsigned long rotl64(unsigned long rs, unsigned n) {
return (rs << n) | (rs >> (64-n));
}
unsigned long rldicl(unsigned long rs, unsigned sh, unsigned mb) {
return rotl64(rs, sh) & ((1UL << (64 - mb)) - 1);
}
unsigned long extrdi(unsigned long ry, unsigned n, unsigned b) {
return rldicl(ry, b+n, 64-n);
}
Upvotes: 1
Reputation: 1503
The ISA says extrdi
is 'Extract and right justify immediate', and it's an extended mnemonic for rldicl
('Rotate left double-word immediate and clear left') - v2.07 pg 717. So your statement is equivalent to rldicl r0, r0, 52, 56
.
So, you want to extract 8 bits starting at position 44, and then right justify it, which would make it the least-significant 8 bits. It's worth noting that IBM bit numbers go the opposite way to what you'd probably expect: conventional bit = 63 - IBM bit
. So IBM bits 44 to 51 are 'conventional' bit number 12 to 19.
We simply shift down so that bit 12 becomes bit 0 and bit 19 becomes bit 7 - a shift of 12 places. We then need to mask it so we only get the least-significant 8 bits.
unsigned long extrdi(unsigned long a) {
return (a >> 12) & 0xff;
}
Looking on godbolt.org: https://godbolt.org/z/rGe3EW, we see this is indeed:
extrdi:
rldicl 3,3,52,56
blr
.long 0
.byte 0,0,0,0,0,0,0,0
(r3 is the argument and return register)
Upvotes: 4