Add jump encodings to RISC-V.
Fix a bug in gen_encoding.py when dealing with non-polymorphic instructions where the type variable is None in Python, VOID in Rust.
This commit is contained in:
@@ -75,7 +75,8 @@ ebb0:
|
||||
[-,%x7] v140 = iconst.i32 0x12345000 ; bin: 123453b7
|
||||
[-,%x16] v141 = iconst.i32 0xffffffff_fedcb000 ; bin: fedcb837
|
||||
|
||||
jump ebb1
|
||||
brz v1, ebb3
|
||||
fallthrough ebb1
|
||||
|
||||
; Control Transfer Instructions
|
||||
|
||||
@@ -110,10 +111,15 @@ ebb1:
|
||||
fallthrough ebb2
|
||||
|
||||
ebb2:
|
||||
; beq x, %x0
|
||||
brz v1, ebb2 ; bin: 00050063
|
||||
; bne x, %x0
|
||||
brnz v1, ebb2 ; bin: fe051ee3
|
||||
; jal %x0, 0x00000
|
||||
jump ebb2 ; bin: 0000006f
|
||||
|
||||
return
|
||||
ebb3:
|
||||
; beq x, %x0
|
||||
brz v1, ebb3 ; bin: 00050063
|
||||
; bne x, %x0
|
||||
brnz v1, ebb3 ; bin: fe051ee3
|
||||
|
||||
; jal %x0, 0x1ffff4
|
||||
jump ebb2 ; bin: ff5ff06f
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ class Level2Table(object):
|
||||
level2_doc[self.hash_table_offset].append(
|
||||
'{:06x}: {}, {} entries'.format(
|
||||
self.hash_table_offset,
|
||||
self.ty.name,
|
||||
self.ty,
|
||||
self.hash_table_len))
|
||||
level2_hashtables.extend(hash_table)
|
||||
|
||||
@@ -405,7 +405,7 @@ def emit_level1_hashtable(cpumode, level1, offt, fmt):
|
||||
"""
|
||||
def hash_func(level2):
|
||||
# type: (Level2Table) -> int
|
||||
return level2.ty.number
|
||||
return level2.ty.number if level2.ty is not None else 0
|
||||
hash_table = compute_quadratic(level1.tables.values(), hash_func)
|
||||
|
||||
with fmt.indented(
|
||||
@@ -415,11 +415,12 @@ def emit_level1_hashtable(cpumode, level1, offt, fmt):
|
||||
if level2:
|
||||
l2l = int(math.log(level2.hash_table_len, 2))
|
||||
assert l2l > 0, "Hash table too small"
|
||||
tyname = level2.ty.name if level2.ty is not None else 'void'
|
||||
fmt.line(
|
||||
'Level1Entry ' +
|
||||
'{{ ty: types::{}, log2len: {}, offset: {:#08x} }},'
|
||||
.format(
|
||||
level2.ty.name.upper(),
|
||||
tyname.upper(),
|
||||
l2l,
|
||||
level2.hash_table_offset))
|
||||
else:
|
||||
|
||||
@@ -5,8 +5,8 @@ from __future__ import absolute_import
|
||||
from base import instructions as base
|
||||
from base.immediates import intcc
|
||||
from .defs import RV32, RV64
|
||||
from .recipes import OPIMM, OPIMM32, OP, OP32, LUI, BRANCH
|
||||
from .recipes import JALR, R, Rshamt, Ricmp, I, Iicmp, Iret, U, SB, SBzero
|
||||
from .recipes import OPIMM, OPIMM32, OP, OP32, LUI, BRANCH, JALR, JAL
|
||||
from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret, U, UJ, SB, SBzero
|
||||
from .settings import use_m
|
||||
from cdsl.ast import Var
|
||||
|
||||
@@ -81,6 +81,10 @@ RV64.enc(base.imul.i32, R, OP32(0b000, 0b0000001), isap=use_m)
|
||||
|
||||
# Control flow.
|
||||
|
||||
# Unconditional branches.
|
||||
RV32.enc(base.jump, UJ, JAL())
|
||||
RV64.enc(base.jump, UJ, JAL())
|
||||
|
||||
# Conditional branches.
|
||||
for cond, f3 in [
|
||||
(intcc.eq, 0b000),
|
||||
|
||||
@@ -12,7 +12,7 @@ from __future__ import absolute_import
|
||||
from cdsl.isa import EncRecipe
|
||||
from cdsl.predicates import IsSignedInt
|
||||
from base.formats import Binary, BinaryImm, MultiAry, IntCompare, IntCompareImm
|
||||
from base.formats import UnaryImm, BranchIcmp, Branch
|
||||
from base.formats import UnaryImm, BranchIcmp, Branch, Jump
|
||||
from .registers import GPR
|
||||
|
||||
# The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit
|
||||
@@ -47,6 +47,11 @@ def JALR(funct3=0):
|
||||
return 0b11001 | (funct3 << 5)
|
||||
|
||||
|
||||
def JAL():
|
||||
# type: () -> int
|
||||
return 0b11011
|
||||
|
||||
|
||||
def OPIMM(funct3, funct7=0):
|
||||
# type: (int, int) -> int
|
||||
assert funct3 <= 0b111
|
||||
@@ -112,6 +117,9 @@ U = EncRecipe(
|
||||
'U', UnaryImm, size=4, ins=(), outs=GPR,
|
||||
instp=IsSignedInt(UnaryImm.imm, 32, 12))
|
||||
|
||||
# UJ-type unconditional branch instructions.
|
||||
UJ = EncRecipe('UJ', Jump, size=4, ins=(), outs=(), branch_range=(0, 21))
|
||||
|
||||
# SB-type branch instructions.
|
||||
# TODO: These instructions have a +/- 4 KB branch range. How to encode that
|
||||
# constraint?
|
||||
|
||||
@@ -279,3 +279,42 @@ fn recipe_sbzero<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut
|
||||
panic!("Expected Branch format: {:?}", func.dfg[inst]);
|
||||
}
|
||||
}
|
||||
|
||||
/// UJ-type jump instructions.
|
||||
///
|
||||
/// 31 11 6
|
||||
/// imm rd opcode
|
||||
/// 12 7 0
|
||||
///
|
||||
/// Encoding bits: `opcode[6:2]`
|
||||
fn put_uj<CS: CodeSink + ?Sized>(bits: u16, imm: i64, rd: RegUnit, sink: &mut CS) {
|
||||
let bits = bits as u32;
|
||||
let opcode5 = bits & 0x1f;
|
||||
let rd = rd as u32 & 0x1f;
|
||||
|
||||
assert!(is_signed_int(imm, 21, 1), "UJ out of range {:#x}", imm);
|
||||
let imm = imm as u32;
|
||||
|
||||
// 0-6: opcode
|
||||
let mut i = 0x3;
|
||||
i |= opcode5 << 2;
|
||||
i |= rd << 7;
|
||||
|
||||
// The displacement is completely hashed up.
|
||||
i |= imm & 0xff000;
|
||||
i |= ((imm >> 11) & 0x1) << 20;
|
||||
i |= ((imm >> 1) & 0x3ff) << 21;
|
||||
i |= ((imm >> 20) & 0x1) << 31;
|
||||
|
||||
sink.put4(i);
|
||||
}
|
||||
|
||||
fn recipe_uj<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
|
||||
if let InstructionData::Jump { destination, .. } = func.dfg[inst] {
|
||||
let dest = func.offsets[destination] as i64;
|
||||
let disp = dest - sink.offset() as i64;
|
||||
put_uj(func.encodings[inst].bits(), disp, 0, sink);
|
||||
} else {
|
||||
panic!("Expected Jump format: {:?}", func.dfg[inst]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user