Ali Hassan
Ali Hassan

Reputation: 966

Trying to understand how jump instruction calculate the address when different Program counter present

Currently I am understanding a RISC-V(ISA) instruction set architecture with three extensions I, M, and C extension. Almost I have understood all the instructions of I, M, and C extension but I haven't found yet that how jumps and branches instructions work when 2 different counter presents and how they calculate the address of the next instruction and the immediate value of the label which we are giving.

Note: In C-extension the Program counter increment with +2, because C means compressed and it contains 16-bit instructions. While in I and M extension the Program counter increment with +4 because I and M contain 32-bit instructions.

I have two examples that I want to understand how jumps and branches calculate the address of the next instructions and immediate value of the label that we are given. Can anyone please provide me or explain the formula of calculating the next address of instruction when jumps or branches occur. I am providing two examples of RISC-V assembly. Kindly please help me. Thanks in advance.

Example 1:

0x0  addi x5,x0,12  #x5 = x0 + 12
0x4  c.addi x6,0    #x6 = x6 + 0 
     l1:
0x6  c.addi x8,6    #x8 = x8 + 6 
0x8  c.jal end      # ?
0xA  c.li x7,2      #x7 = x7 + 2
     end:
0xC  c.mv x6,x8     #x6 = x8
0xE  bne x5,x6,l1   # ?
0x12 c.add x7,x6    # x7 = x7 + x6
0x14 add x8,x5,x7   # x8 = x5 + x7
0x18 c.jal end      # ?

Example 2:

0x0  addi x5,x0,12  #x5 = x0 + 12
0x4  c.addi x6,1    #x6 = x6 + 1
     l1:
0x6  c.li x7,1      #x7 = x7 + 1
0x8  beq x6,x7,end  # ?
0xC  c.add x7,x6    #x7 = x7 + x6
end:
0xE  add x8,x5,x7   #x8 = x5 + x7
0x12 c.jal l1       # ?
0x14 sub x9,x8,x6   #x9 = x8 + x6

Upvotes: 0

Views: 2434

Answers (2)

Erik Eidt
Erik Eidt

Reputation: 26646

bne and beq are 32-bit instructions that allow for a 13-bit immediate byte offset, which only requires 12 bits to store since the low bit is always zero and thus not stored (all instructions are multiples of 2 bytes).

The 13-bit immediate is used in a pc-relative addressing mode, so when the conditional branch is taken, the hardware computes:

pc' := pc + signExtend(immediate12 ## 0)

where pc' is the next pc, and ## represents bitwise concatenation.  When the branch is not taken it computes the usual pc' := pc + 4 which is sequential flow.

Sign extension is done to interpret the immediate as signed, and, this means that the immediate can be negative or positive, to jump backwards or forwards, respectively.

The 12 bits of the 13-bit branch target immediate are stored distributed among several fields throughout the instruction.  These fields are selected for good overlap with other immediates, and to allow the register fields to remain in the same place relative to other instruction formats.


The c.jal instruction encodes a 12-bit immediate, within a 16-bit instruction; The immediate is encoded in 11-bits (again because the low bit is always zero, so no need to represent it in the instruction).  The hardware takes the 11-bit encoded immediate, adds an extra 0 to the end to make it 12 bits, and then sign extends to full width (we could also say it first sign extends to full width, then multiplies by 2 — same result).  The operation is pc' := pc + signExtend(imm11 ## 0) where ## is concatenation.

Once we know how the processor computes the branch target pc, pc', we simply reverse computation when assembling instructions.  Subtract the difference between the target label (to) and the current pc (from), then divide by 2 and truncate to fit the field width.

If truncation changes the numeric value, then the immediate is too large for the field of the instruction and thus cannot be encoded.


Inline the encoded immediate field's value:

0x0  addi x5,x0,12  #x5 = x0 + 12
0x4  c.addi x6,0    #x6 = x6 + 0 
     l1:
0x6  c.addi x8,6    #x8 = x8 + 6 
0x8  c.jal end      # ?                  **(to-from)/2=(0xC-0x8)/2=2**
0xA  c.li x7,2      #x7 = x7 + 2
     end:
0xC  c.mv x6,x8     #x6 = x8
0xE  bne x5,x6,l1   # ?                  **(0x6-0xE)/2=-4**
0x12 c.add x7,x6    # x7 = x7 + x6
0x14 add x8,x5,x7   # x8 = x5 + x7
0x18 c.jal end      # ?                  **(0xC-0x18)/2=-6**

0x0  addi x5,x0,12  #x5 = x0 + 12
0x4  c.addi x6,1    #x6 = x6 + 1
     l1:
0x6  c.li x7,1      #x7 = x7 + 1
0x8  beq x6,x7,end  # ?                    **(0xE-0x8)/2=3**
0xC  c.add x7,x6    #x7 = x7 + x6
end:
0xE  add x8,x5,x7   #x8 = x5 + x7
0x12 c.jal l1       # ?                    **(0x6-0x12)/2=-6**
0x14 sub x9,x8,x6   #x9 = x8 + x6

Sign extension is used to make a short signed field into a full width value.

An 11 bit encoded immediate, as in c.jal, using -6 and +6 as examples, would look like this in binary:

# Example using -6
                     * The bit under the * is the MSB
                     |
                     11111111010    # -6 in 11 bits

11111111111111111111111111111010    # -6 in 32 bits
********************* Copied from the MSB in 11 bits


# Example using +6
                     * The bit under the * is the MSB
                     |
                     00000000110    # 6 in 11 bits

00000000000000000000000000000110    # 6 in 32 bits
*********************  Copied from the MSB in 11 bits

The Most Significant Bit is the top bit and if 1 means the number is negative.  In order to preserve the value when widening (e.g. from 11 to 32 bits), propagate the MSB in the shorter field across all the bits of extra width.

Upvotes: 1

Amit
Amit

Reputation: 266

Not sure if this is the best way to do it

<p id="x"></p> // replace **{{c}}** blank element hence it will impact anything

After the successful ajax call

success: function(data){ // data will hold whatever is returned from the url
           $("#x").html(data['c']); // This will populate the p element with your value
           alert("Hello");
         },

You can also hide the ment

Upvotes: 1

Related Questions