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)