Shift Instructions

The shift operations in C are

v>>n (shift v right n bits)
v<<n (shift v left n bits)
If the variable v is unsigned, a right shift is logical and zeros are shifted in from the left. If the variable v is signed, a right shift is arithmetic and the sign bit is shifted in from the left (sign extension).

Instruction Description Function
ROTR Rotate Word Right Rd = Rt[sa-1:0] | Rt[31:sa]
ROTRV Rotate Word Right Variable Rd = Rt[Rs-1:0] | Rt[31:Rs]
SLL Shift Left Logical Rd = Rt << sa
SLLV Shift Left Logical Variable Rd = Rt << Rs[4:0]
SRA Shift Right Arithmetic Rd = (int)Rt >> sa
SRAV Shift Right Arithmetic Variable Rd = (int)Rt >> Rs[4:0]
SRL Shift Right Logical Rd = (uns)Rt >> sa
SRLV Shift Right Logical Variable Rd = (uns)Rt >> Rs[4:0]

C Source

C Source: shift.zip


01: #define PIC32
02: #if defined(PIC32)
03:         #include <p32xxxx.h>
04:         // comment the following line to enable debug output
05:         #define UART2_IO
06:         #include "db_utils.h"
07: #else // Microsoft C
08:         #include <stdio.h>
09:         #define DBPRINTF printf
10:         #define DBPUTS(s)
11: #endif
12: 
13: int main()
14: {
15:         unsigned int na, ns, nv;
16:         na = 0x8000F731;
17:         DBPRINTF("na = 0x%x\n",na);
18: 
19:         // logical shift left
20:         nv = na<<3;
21:         DBPRINTF("na<<3 = 0x%x\n",nv);
22:         // logical shift right
23:         nv = na>>3;
24:         DBPRINTF("na>>3 = 0x%x\n",nv);
25:         // aritmetic shift right
26:         nv = ((signed)na)>>3;
27:         DBPRINTF("((signed)na)>>3 = 0x%x\n",nv);
28: 
29:         // rotate right
30:         nv = (na>>4)|(na<<28);
31:         DBPRINTF("rot right 4 = 0x%x\n",nv);
32: 
33:         // rotate left
34:         nv = (na<<4)|(na>>28);
35:         DBPRINTF("rot left 4 = 0x%x\n",nv);
36: 
37:         // use variable as shift amount
38:         ns = 5;
39:         DBPRINTF("Use variable as shift amount\n ns = %d\n",ns);
40: 
41:         nv = na>>ns;
42:         DBPRINTF("na>>ns = 0x%x\n",nv);
43: 
44:         nv = na<<ns;
45:         DBPRINTF("na<<ns = 0x%x\n",nv);
46: 
47:         ns = 8;
48:         // rotate right
49:         nv = (na>>ns)|(na<<(32-ns));
50:         DBPRINTF("rot right 8 = 0x%x\n",nv);
51: 
52:         // rotate left
53:         nv = (na<<ns)|(na>>(32-ns));
54:         DBPRINTF("rot left 8 = 0x%x\n",nv);
55: 
56:         DBPUTS("Program terminated. Click HALT and then RESET to stop the microcontroller. \n");
57:         return 0;
58: }


Results

Comment out the PIC32 definition in line 1 and you can run this program with Microsoft C. The results are below

na = 0x8000f731
na<<3 = 0x7b988
na>>3 = 0x10001ee6
((signed)na)>>3 = 0xf0001ee6
rot right 4 = 0x18000f73
rot left 4 = 0xf7318
Use variable as shift amount
 ns = 5
na>>ns = 0x40007b9
na<<ns = 0x1ee620
rot right 8 = 0x318000f7
rot left 8 = 0xf73180

Disassembly Listing

Note that for lines 30 and 34 the compiler substitutes the single rotate instruction. Note further in line 34 that the compiler rotates right (32 - n) when asked to rotate left by n.

---  C:\pic32\test\shift1.c  ---------------------------------------------------------------------
1:                   #define PIC32
2:                   #if defined(PIC32)
3:                   	#include <p32xxxx.h>
4:                   	// comment the following line to enable debug output
5:                   	#define UART2_IO
6:                   	#include "db_utils.h"
7:                   #else // Microsoft C
8:                   	#include <stdio.h>
9:                   	#define DBPRINTF printf
10:                  	#define DBPUTS(s)
11:                  #endif
12:                  
13:                  int main()
14:                  {
9D000018  27BDFFE8   addiu       sp,sp,-24
9D00001C  AFBE0010   sw          s8,16(sp)
9D000020  03A0F021   addu        s8,sp,zero
15:                  	unsigned int na, ns, nv;
16:                  	na = 0x8000F731;
9D000024  3C028000   lui         v0,0x8000
9D000028  3442F731   ori         v0,v0,0xf731
9D00002C  AFC20000   sw          v0,0(s8)
17:                  	DBPRINTF("na = 0x%x\n",na);
18:                  
19:                  	// logical shift left
20:                  	nv = na<<3;
9D000030  8FC20000   lw          v0,0(s8)
9D000034  000210C0   sll         v0,v0,0x3
9D000038  AFC20008   sw          v0,8(s8)
21:                  	DBPRINTF("na<<3 = 0x%x\n",nv);
22:                  	// logical shift right
23:                  	nv = na>>3;
9D00003C  8FC20000   lw          v0,0(s8)
9D000040  000210C2   srl         v0,v0,0x3
9D000044  AFC20008   sw          v0,8(s8)
24:                  	DBPRINTF("na>>3 = 0x%x\n",nv);
25:                  	// aritmetic shift right
26:                  	nv = ((signed)na)>>3;
9D000048  8FC20000   lw          v0,0(s8)
9D00004C  000210C3   sra         v0,v0,0x3
9D000050  AFC20008   sw          v0,8(s8)
27:                  	DBPRINTF("((signed)na)>>3 = 0x%x\n",nv);
28:                  
29:                  	// rotate right
30:                  	nv = (na>>4)|(na<<28);
9D000054  8FC20000   lw          v0,0(s8)
9D000058  00221102   rotr        v0,v0,0x4
9D00005C  AFC20008   sw          v0,8(s8)
31:                  	DBPRINTF("rot right 4 = 0x%x\n",nv);
32:                  
33:                  	// rotate left
34:                  	nv = (na<<4)|(na>>28);
9D000060  8FC20000   lw          v0,0(s8)
9D000064  00221702   rotr        v0,v0,0x1c
9D000068  AFC20008   sw          v0,8(s8)
35:                  	DBPRINTF("rot left 4 = 0x%x\n",nv);
36:                  
37:                  	// use variable as shift amount
38:                  	ns = 5;
9D00006C  24020005   addiu       v0,zero,5
9D000070  AFC20004   sw          v0,4(s8)
39:                  	DBPRINTF("Use variable as shift amount\n ns = %d\n",ns);
40:                  
41:                  	nv = na>>ns;
9D000074  8FC30000   lw          v1,0(s8)
9D000078  8FC20004   lw          v0,4(s8)
9D00007C  00431006   srlv        v0,v1,v0
9D000080  AFC20008   sw          v0,8(s8)
42:                  	DBPRINTF("na>>ns = 0x%x\n",nv);
43:                  
44:                  	nv = na<<ns;
9D000084  8FC30000   lw          v1,0(s8)
9D000088  8FC20004   lw          v0,4(s8)
9D00008C  00431004   sllv        v0,v1,v0
9D000090  AFC20008   sw          v0,8(s8)
45:                  	DBPRINTF("na<<ns = 0x%x\n",nv);
46:                  
47:                  	ns = 8;
9D000094  24020008   addiu       v0,zero,8
9D000098  AFC20004   sw          v0,4(s8)
48:                  	// rotate right
49:                  	nv = (na>>ns)|(na<<(32-ns));
9D00009C  8FC30000   lw          v1,0(s8)
9D0000A0  8FC20004   lw          v0,4(s8)
9D0000A4  00431046   rotrv       v0,v1,v0
9D0000A8  AFC20008   sw          v0,8(s8)
50:                  	DBPRINTF("rot right 8 = 0x%x\n",nv);
51:                  
52:                  	// rotate left
53:                  	nv = (na<<ns)|(na>>(32-ns));
9D0000AC  8FC30000   lw          v1,0(s8)
9D0000B0  8FC20004   lw          v0,4(s8)
9D0000B4  00021023   subu        v0,zero,v0
9D0000B8  00431046   rotrv       v0,v1,v0
9D0000BC  AFC20008   sw          v0,8(s8)
54:                  	DBPRINTF("rot left 8 = 0x%x\n",nv);
55:                  
56:                  	DBPUTS("Program terminated. Click HALT and then RESET to stop the microcontroller. \n");
57:                  	return 0;
9D0000C0  00001021   addu        v0,zero,zero
58:                  }
9D0000C4  03C0E821   addu        sp,s8,zero
9D0000C8  8FBE0010   lw          s8,16(sp)
9D0000CC  27BD0018   addiu       sp,sp,24
9D0000D0  03E00008   jr          ra
9D0000D4  00000000   nop         


Maintained by John Loomis, updated Sat Aug 09 11:32:24 2008