Skip to content

Commit 5ef285f

Browse files
committed
Enhance the jump instruction (use RRO like call)
1 parent 99627a5 commit 5ef285f

File tree

5 files changed

+53
-35
lines changed

5 files changed

+53
-35
lines changed

docs/spec.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -289,21 +289,27 @@ shiftr <reg>, <imm>
289289

290290
Will effectively perform `reg = reg >> imm`. No side effects (at the moment).
291291

292-
### jump (immediate address)
292+
### jump (using a register)
293+
294+
Format: RRO
295+
296+
Opcode: `7'h4`
293297

294298
```
295-
jump <imm>
299+
jump <reg> [, off <imm>]
296300
```
297301

298-
This instruction will set register `pc` to the specified `<imm>` value.
299-
300-
### jump (using a register)
302+
This instruction will set register `pc` to the value taken of `<reg> + <imm>` (`<imm>` can be negative, so backward jumps are possible)
301303

302304
```
303-
jump <reg>
305+
jump <imm>
304306
```
305307

306-
This instruction will set register `pc` to the value taken from register `<reg>`.
308+
The assembler also supports this syntactic sugar syntax (so you can eg. jump to a label etc). When this is used the assembler will calculate the proper offset and implicitly use the `pc` register, turning it into this call:
309+
310+
```
311+
jump pc, off <offset from current pc>
312+
```
307313

308314
### call (register, offset)
309315

@@ -317,6 +323,12 @@ call <reg> off <imm>
317323

318324
This instruction will effectively decrement the `sp` register by 8, issue a bus write cycle to write value of `pc + 8` into address `sp`, and make a jump to `reg + imm`.
319325

326+
```
327+
call <imm>
328+
```
329+
330+
The assembler also supports this syntactic sugar syntax. In this case, just like in the `jump` case, the assembler will implicitly use the `pc` register, and calculate the correct offset.
331+
320332
### return
321333

322334
Format: I

rtl/cpu.v

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -401,16 +401,14 @@ module cpu (
401401
end
402402
end // `OP_LOAD
403403
`OP_JUMP: begin
404-
if (instr_format == `INSTR_FORMAT_I) begin
405-
// $display("%g: jump 0h%01x", $time, instr_i_imm);
406-
407-
cpu_regs_in <= instr_i_imm;
408-
end else if (instr_format == `INSTR_FORMAT_RIS) begin
409-
// $display("%g: jump r%1d (h'%x)", $time, instr_ris_reg, instr_dst_reg_val);
410-
411-
cpu_regs_in <= instr_dst_reg_val;
412-
end
404+
if (instr_rro_off[40] == 1'b1)
405+
$display("%g: jump r%1d (h'%x) off -0x%1x", $time,
406+
instr_rro_dst, instr_dst_reg_val, ~instr_rro_off + 1);
407+
else
408+
$display("%g: jump r%1d (h'%x) off 0x%1x", $time,
409+
instr_rro_dst, instr_dst_reg_val, instr_rro_off);
413410

411+
cpu_regs_in <= $signed(instr_dst_reg_val) + $signed(instr_rro_off);
414412
cpu_regs_write <= 1'b1;
415413
cpu_regs_id <= `REG_PC;
416414
cpu_state <= `STATE_REG_WRITE;

rtl/rom.v

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,16 @@ module rom (
5353
16'h0008: r_dat_o = 64'h1687800000008000; // add r30, 0x400 0
5454
16'h0010: r_dat_o = 64'h0286c01002000010; // set r27, 0x80100000 shl 16
5555
16'h0018: r_dat_o = 64'h02804000000002a0; // set r1, 0x15
56-
16'h0020: r_dat_o = 64'h1a07c00000000008; // call r31 off 8
57-
16'h0028: r_dat_o = 64'h0c87c00000000200; // sub r31, 16
58-
16'h0030: r_dat_o = 64'h0407360000000000; // load r28, r27
59-
16'h0038: r_dat_o = 64'h0a87000000000000; // testbit r28, 0
60-
16'h0040: r_dat_o = 64'h0948800000000030; // jump.nz 0x800000000030
61-
16'h0048: r_dat_o = 64'h0606c20000000010; // store r1, r27 off 16
62-
16'h0050: r_dat_o = 64'h1d00000000000000; // return
56+
16'h0020: r_dat_o = 64'h1a07c00000000020; // call r31 off 32
57+
16'h0028: r_dat_o = 64'h028680000004e200; // set r26, 0x2710
58+
16'h0030: r_dat_o = 64'h0c86800000000020; // sub r26, 1
59+
16'h0038: r_dat_o = 64'h084fc1fffffffff0; // jump.nz r31 off -16
60+
16'h0040: r_dat_o = 64'hff00000000000000; // halt
61+
16'h0048: r_dat_o = 64'h0407360000000000; // load r28, r27
62+
16'h0050: r_dat_o = 64'h0a87000000000000; // testbit r28, 0
63+
16'h0058: r_dat_o = 64'h084fc1ffffffffe8; // jump.nz r31 off -24
64+
16'h0060: r_dat_o = 64'h0606c20000000010; // store r1, r27 off 16
65+
16'h0068: r_dat_o = 64'h1d00000000000000; // return
6366
default: r_dat_o = 64'hfe00000000000000; // halt by default
6467
endcase
6568
end

tools/asm.lark

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
start: instr*
22
instr: /nop/ ["." cond] -> nop
3-
| /jump/ ["." cond] expr -> jump_i
4-
| /jump/ ["." cond] reg -> jump_ris
3+
| /jump/ ["." cond] expr -> jump_expr
4+
| /jump/ ["." cond] reg ["off" expr] -> jump_rro
55
| /call/ ["." cond] expr -> call_expr
66
| /call/ ["." cond] reg ["off" expr] -> call_rro
77
| /return/ ["." cond] -> return_

tools/asm.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,8 @@ def __init__(self, mnem, opcode, format, cond, **kwargs):
190190
super().__init__(mnem, opcode, format, cond, **kwargs)
191191

192192
def __str__(self):
193-
if self.format == Format.I:
194-
return "jump{} 0x{:x}".format(self.cond, self.imm)
195-
elif self.format == Format.RIS:
196-
return "jump{} r{}".format(self.cond, self.dst_reg)
193+
if self.format == Format.RRO:
194+
return "jump{} r{} {}".format(self.cond, self.dst_reg, self.off)
197195

198196
class Call(Instr):
199197
def __init__(self, mnem, opcode, format, cond, **kwargs):
@@ -339,20 +337,27 @@ def halt(self, op, cond):
339337
self.inc_pc()
340338
return Halt("halt", 0x7f, Cond(cond))
341339

342-
def jump_i(self, op, cond, imm):
340+
def jump_expr(self, op, cond, imm):
343341
self.inc_pc()
344-
return Jump("jump", 0x04, Format.I, Cond(cond), imm = imm)
342+
# this offset from pc must be calculated after it's been incremented
343+
# since when the instruction is executed by the CPU, the pc register
344+
# points to the next instruction, not current
345+
offset_from_pc = imm - self.current_pc
346+
347+
return Jump("jump", 0x04, Format.RRO, Cond(cond),
348+
dst_reg = 31, src_reg = 0x0, off = Off(offset_from_pc))
345349

346-
def jump_ris(self, op, cond, reg):
350+
def jump_rro(self, op, cond, reg, off):
347351
self.inc_pc()
348-
return Jump("jump", 0x04, Format.RIS, Cond(cond), dst_reg = reg)
352+
return Jump("jump", 0x04, Format.RRO, Cond(cond),
353+
dst_reg = reg, src_reg = 0x0, off = Off(off))
349354

350-
def call_expr(self, op, cond, special_imm):
355+
def call_expr(self, op, cond, imm):
351356
self.inc_pc()
352357
# this offset from pc must be calculated after it's been incremented
353358
# since when the instruction is executed by the CPU, the pc register
354359
# points to the next instruction, not current
355-
offset_from_pc = special_imm - self.current_pc
360+
offset_from_pc = imm - self.current_pc
356361

357362
return Call("call", 0x0d, Format.RRO, Cond(cond),
358363
dst_reg = 31, src_reg = 0x0, off = Off(offset_from_pc))

0 commit comments

Comments
 (0)