Jump Instructions

Jump instructions modify the program counter so that executation continues at a specified memory address, no matter (almost) the value of the current program counter. Branch instructions, by contrast, are always relative to the current program counter.

There are four different basic jump instructions. You can specify a register that contains the jump target address or you can specify the jump target address as an immediate operand. For each choice, you can place a return address (PC+8) in a register for later use.

Instruction Description Function
J Unconditional Jump PC = PC[31:28] | offset<<2
JAL Jump and Link
GPR[31] = PC + 8
PC = PC[31:28] | offset<<2
JALR Jump and Link Register
Rd = PC + 8
PC = Rs
JR Jump Register PC = Rs

Notes:

The JALR instruction allows you to choose the destination register. The JAL instruction supposes that the destination register is r31 (ra).

GPR[31], above, means "general purpose register 31" or just r31.

The immediate operand, or jump target address, defines only the low 28-bits of the address. The upper four bits are taken from the program counter. In the PIC32 Starter Kit, that would be the leading hex digit 0x9.

If you look through the disassembly listing you will see that only the JAL and JR instructions are used. The appending NOP satisifies a delay slot requirement for the pipelined MIPS processor.

Consider the following code snippet:

9D000040  0F40001F   jal         0x9d00007c
9D000044  00000000   nop         
9D000048  AFC20018   sw          v0,24(s8)
The value of ra after the jump is 0x9D000048 (check the CPU registers during simulation). The JAL opcode is 0x03. The jump target operand is 0x0340001F, which is 0x0d00007c after shifting left 2 bits, and the final target is 0x9d00007c.

There is one new instruction in the disassembly listing. Right after the divide instruction, you find teq, or "trap on equal", which calls the exception processor if the trap condition is satisfied. In this case, the check is for a divide by zero.

C Source

Source: jump.zip


01: // comment the following line to enable Microsoft C
02: #define PIC32
03: #if defined(PIC32)
04: #include <p32xxxx.h>
05:         // comment the following line to enable debug output
06: #define UART2_IO
07: #include "db_utils.h"
08: #else // Microsoft C
09: #include <stdio.h>
10: #define DBPRINTF printf
11: #define DBPUTS(s)
12: #endif
13: 
14: int multiply_them(int a, int b);
15: int divide_them(int a, int b);
16: 
17: int main()
18: {
19:         int n1, n2, n3, n4;
20:         n1 = 24;
21:         n2 =  4;
22:         n3 = multiply_them(n1,n2);
23:         n4 = divide_them(n1,n2);
24:         
25:         DBPRINTF("n1 = %d  n2 = %d product %d division %d\n",n1,n2,n3,n4);
26:         DBPUTS("Program terminated. Click HALT and then RESET to stop the microcontroller. \n");
27:         return 0;
28: }
29: 
30: int multiply_them(int a, int b)
31: {
32:         int c;
33:         c = a*b;
34:         return c;
35: }
36: int divide_them(int a, int b)
37: {
38:         int c;
39:         c = a/b;
40:         return c;
41: }


Results

Here are the results using Microsoft C:

n1 = 24  n2 = 4 product 96 division 6

Disassembly Listing

---  C:\pic32\test\jump.c  -----------------------------------------------------------------------
1:                   // comment the following line to enable Microsoft C
2:                   #define PIC32
3:                   #if defined(PIC32)
4:                   #include <p32xxxx.h>
5:                   // comment the following line to enable debug output
6:                   #define UART2_IO
7:                   #include "db_utils.h"
8:                   #else // Microsoft C
9:                   #include <stdio.h>
10:                  #define DBPRINTF printf
11:                  #define DBPUTS(s)
12:                  #endif
13:                  
14:                  int multiply_them(int a, int b);
15:                  int divide_them(int a, int b);
16:                  
17:                  int main()
18:                  {
9D000018  27BDFFD8   addiu       sp,sp,-40
9D00001C  AFBF0024   sw          ra,36(sp)
9D000020  AFBE0020   sw          s8,32(sp)
9D000024  03A0F021   addu        s8,sp,zero
19:                      int n1, n2, n3, n4;
20:                      n1 = 24;
9D000028  24020018   addiu       v0,zero,24
9D00002C  AFC20010   sw          v0,16(s8)
21:                      n2 =  4;
9D000030  24020004   addiu       v0,zero,4
9D000034  AFC20014   sw          v0,20(s8)
22:                      n3 = multiply_them(n1,n2);
9D000038  8FC40010   lw          a0,16(s8)
9D00003C  8FC50014   lw          a1,20(s8)
9D000040  0F40001F   jal         0x9d00007c
9D000044  00000000   nop         
9D000048  AFC20018   sw          v0,24(s8)
23:                      n4 = divide_them(n1,n2);
9D00004C  8FC40010   lw          a0,16(s8)
9D000050  8FC50014   lw          a1,20(s8)
9D000054  0F40002E   jal         0x9d0000b8
9D000058  00000000   nop         
9D00005C  AFC2001C   sw          v0,28(s8)
24:                      
25:                      DBPRINTF("n1 = %d  n2 = %d product %d division %d\n",n1,n2,n3,n4);
26:                      DBPUTS("Program terminated. Click HALT and then RESET to stop the microcontroller. \n");
27:                      return 0;
9D000060  00001021   addu        v0,zero,zero
28:                  }
9D000064  03C0E821   addu        sp,s8,zero
9D000068  8FBF0024   lw          ra,36(sp)
9D00006C  8FBE0020   lw          s8,32(sp)
9D000070  27BD0028   addiu       sp,sp,40
9D000074  03E00008   jr          ra
9D000078  00000000   nop         
29:                  
30:                  int multiply_them(int a, int b)
31:                  {
9D00007C  27BDFFF0   addiu       sp,sp,-16
9D000080  AFBE0008   sw          s8,8(sp)
9D000084  03A0F021   addu        s8,sp,zero
9D000088  AFC40010   sw          a0,16(s8)
9D00008C  AFC50014   sw          a1,20(s8)
32:                      int c;
33:                      c = a*b;
9D000090  8FC30010   lw          v1,16(s8)
9D000094  8FC20014   lw          v0,20(s8)
9D000098  70621002   mul         v0,v1,v0
9D00009C  AFC20000   sw          v0,0(s8)
34:                      return c;
9D0000A0  8FC20000   lw          v0,0(s8)
35:                  }
9D0000A4  03C0E821   addu        sp,s8,zero
9D0000A8  8FBE0008   lw          s8,8(sp)
9D0000AC  27BD0010   addiu       sp,sp,16
9D0000B0  03E00008   jr          ra
9D0000B4  00000000   nop         
36:                  int divide_them(int a, int b)
37:                  {
9D0000B8  27BDFFF0   addiu       sp,sp,-16
9D0000BC  AFBE0008   sw          s8,8(sp)
9D0000C0  03A0F021   addu        s8,sp,zero
9D0000C4  AFC40010   sw          a0,16(s8)
9D0000C8  AFC50014   sw          a1,20(s8)
38:                      int c;
39:                      c = a/b;
9D0000CC  8FC30010   lw          v1,16(s8)
9D0000D0  8FC20014   lw          v0,20(s8)
9D0000D4  0062001A   div         v1,v0
9D0000D8  004001F4   teq         v0,zero
9D0000DC  00001012   mflo        v0
9D0000E0  AFC20000   sw          v0,0(s8)
40:                      return c;
9D0000E4  8FC20000   lw          v0,0(s8)
41:                  }
9D0000E8  03C0E821   addu        sp,s8,zero
9D0000EC  8FBE0008   lw          s8,8(sp)
9D0000F0  27BD0010   addiu       sp,sp,16
9D0000F4  03E00008   jr          ra
9D0000F8  00000000   nop         


Maintained by John Loomis, updated Mon Aug 18 20:54:43 2008