20.2.1 Inline Examples
Insert Bit Field
This example demonstrates how to use the INS
instruction to insert a bit
field into a 32-bit wide variable. This function-like macro uses inline assembly to emit
the INS
instruction, which is not commonly generated from C/C++
code.
/* MIPS32r2 insert bits */
#define _ins(tgt,val,pos,sz) __extension__({ \
unsigned int __t = (tgt), __v = (val); \
__asm__ ("ins %0,%z1,%2,%3" /* template */ \
: "+d" (__t) /* output */ \
: "dJ" (__v), "I" (pos), "I" (sz)); /* input */ \
__t; \
})
Here__v
, pos
, and sz
are
input operands. The __v
operand is constrained to be of type 'd' (an
address register) or 'J' (integer zero). The pos
and
sz
operands are constrained to be of type 'I' (a signed 32-bit
constant).
The __t
output operand is constrained to be of type 'd' (an address
register). The '+' modifier means that this operand is both read and written by the
instruction and so the operand is both an input and an output.
The following example shows this macro in use.
unsigned int result;
void example (void)
{
unsigned int insertval = 0x12;
result = 0xAAAAAAAAu;
result = _ins(result, insertval, 4, 8);
/* result is now 0xAAAAA12A */
}
For this example, the compiler may generate assembly code similar to the following.
li $2,-1431699456 # 0xaaaa0000
ori $2,$2,0xaaaa # 0xaaaa0000 | 0xaaaa
li $3,18 # 0x12
ins $2,$3,4,8 # inline assembly
lui $3,%hi(result) # assign the result back
j $31 # return
sw $2,%lo(result)($3)
Multiple Assembler Instructions
This example demonstrates how to use the WSBH
and ROTR
instructions together for a byte swap. The WSBH
instruction is a 32-bit
byte swap within each of the two halfwords. The ROTR
instruction is a
rotate right by immediate. This function-like macro uses inline assembly to create a
“byte-swap word” using instructions that are not commonly generated from C/C++ code.
The following shows the definition of the function-like macro,
_bswapw
.
/* MIPS32r2 byte-swap word */
#define _bswapw(x) __extension__({ \
unsigned int __x = (x), __v; \
__asm__ ("wsbh %0,%1;\n\t" \
"rotr %0,16" /* template */ \
: "=d" (__v) /* output */ \
: "d" (__x)) /* input*/ ; \
__v; \
})
Here __x
is the C expression for the input operand. The operand is
constrained to be of type 'd', which denotes an address register.
The C expression __v
is the output operand. This operand is also
constrained to be of type 'd'. The '=' means that this operand is write-only for this
instruction: the previous value is discarded and replaced by output data.
The function-like macro is shown in the following example assigning to
result
the content of value
, swapped.
unsigned int result;
int example (void)
{
unsigned int value = 0x12345678u;
result = _bswapw(value);
/* result == 0x78563412 */
}
The compiler may generate assembly code similar to the following for this example:
li $2,305397760 # 0x12340000
addiu $2,$2,22136 # 0x12340000 + 0x5678
wsbh $2,$2 # From inline asm
rotr $2,16 # From inline asm
lui $2,%hi(result) # assign back to result
j $31 # return
sw $3,%lo(result)($2)