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:
Jakob Stoklund Olesen
2017-04-06 15:17:57 -07:00
parent fa4f151b9b
commit 896ac935b9
5 changed files with 70 additions and 12 deletions

View File

@@ -75,7 +75,8 @@ ebb0:
[-,%x7] v140 = iconst.i32 0x12345000 ; bin: 123453b7 [-,%x7] v140 = iconst.i32 0x12345000 ; bin: 123453b7
[-,%x16] v141 = iconst.i32 0xffffffff_fedcb000 ; bin: fedcb837 [-,%x16] v141 = iconst.i32 0xffffffff_fedcb000 ; bin: fedcb837
jump ebb1 brz v1, ebb3
fallthrough ebb1
; Control Transfer Instructions ; Control Transfer Instructions
@@ -110,10 +111,15 @@ ebb1:
fallthrough ebb2 fallthrough ebb2
ebb2: ebb2:
; beq x, %x0 ; jal %x0, 0x00000
brz v1, ebb2 ; bin: 00050063 jump ebb2 ; bin: 0000006f
; bne x, %x0
brnz v1, ebb2 ; bin: fe051ee3
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
} }

View File

@@ -300,7 +300,7 @@ class Level2Table(object):
level2_doc[self.hash_table_offset].append( level2_doc[self.hash_table_offset].append(
'{:06x}: {}, {} entries'.format( '{:06x}: {}, {} entries'.format(
self.hash_table_offset, self.hash_table_offset,
self.ty.name, self.ty,
self.hash_table_len)) self.hash_table_len))
level2_hashtables.extend(hash_table) level2_hashtables.extend(hash_table)
@@ -405,7 +405,7 @@ def emit_level1_hashtable(cpumode, level1, offt, fmt):
""" """
def hash_func(level2): def hash_func(level2):
# type: (Level2Table) -> int # 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) hash_table = compute_quadratic(level1.tables.values(), hash_func)
with fmt.indented( with fmt.indented(
@@ -415,11 +415,12 @@ def emit_level1_hashtable(cpumode, level1, offt, fmt):
if level2: if level2:
l2l = int(math.log(level2.hash_table_len, 2)) l2l = int(math.log(level2.hash_table_len, 2))
assert l2l > 0, "Hash table too small" assert l2l > 0, "Hash table too small"
tyname = level2.ty.name if level2.ty is not None else 'void'
fmt.line( fmt.line(
'Level1Entry ' + 'Level1Entry ' +
'{{ ty: types::{}, log2len: {}, offset: {:#08x} }},' '{{ ty: types::{}, log2len: {}, offset: {:#08x} }},'
.format( .format(
level2.ty.name.upper(), tyname.upper(),
l2l, l2l,
level2.hash_table_offset)) level2.hash_table_offset))
else: else:

View File

@@ -5,8 +5,8 @@ from __future__ import absolute_import
from base import instructions as base from base import instructions as base
from base.immediates import intcc from base.immediates import intcc
from .defs import RV32, RV64 from .defs import RV32, RV64
from .recipes import OPIMM, OPIMM32, OP, OP32, LUI, BRANCH from .recipes import OPIMM, OPIMM32, OP, OP32, LUI, BRANCH, JALR, JAL
from .recipes import JALR, R, Rshamt, Ricmp, I, Iicmp, Iret, U, SB, SBzero from .recipes import R, Rshamt, Ricmp, I, Iicmp, Iret, U, UJ, SB, SBzero
from .settings import use_m from .settings import use_m
from cdsl.ast import Var from cdsl.ast import Var
@@ -81,6 +81,10 @@ RV64.enc(base.imul.i32, R, OP32(0b000, 0b0000001), isap=use_m)
# Control flow. # Control flow.
# Unconditional branches.
RV32.enc(base.jump, UJ, JAL())
RV64.enc(base.jump, UJ, JAL())
# Conditional branches. # Conditional branches.
for cond, f3 in [ for cond, f3 in [
(intcc.eq, 0b000), (intcc.eq, 0b000),

View File

@@ -12,7 +12,7 @@ from __future__ import absolute_import
from cdsl.isa import EncRecipe from cdsl.isa import EncRecipe
from cdsl.predicates import IsSignedInt from cdsl.predicates import IsSignedInt
from base.formats import Binary, BinaryImm, MultiAry, IntCompare, IntCompareImm 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 from .registers import GPR
# The low 7 bits of a RISC-V instruction is the base opcode. All 32-bit # 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) return 0b11001 | (funct3 << 5)
def JAL():
# type: () -> int
return 0b11011
def OPIMM(funct3, funct7=0): def OPIMM(funct3, funct7=0):
# type: (int, int) -> int # type: (int, int) -> int
assert funct3 <= 0b111 assert funct3 <= 0b111
@@ -112,6 +117,9 @@ U = EncRecipe(
'U', UnaryImm, size=4, ins=(), outs=GPR, 'U', UnaryImm, size=4, ins=(), outs=GPR,
instp=IsSignedInt(UnaryImm.imm, 32, 12)) 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. # SB-type branch instructions.
# TODO: These instructions have a +/- 4 KB branch range. How to encode that # TODO: These instructions have a +/- 4 KB branch range. How to encode that
# constraint? # constraint?

View File

@@ -279,3 +279,42 @@ fn recipe_sbzero<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut
panic!("Expected Branch format: {:?}", func.dfg[inst]); 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]);
}
}