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 |
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.
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: }
Here are the results using Microsoft C:
n1 = 24 n2 = 4 product 96 division 6
--- 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