| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| from typing import Dict |
| |
| from .model import OTBNModel |
| from .isa import (OTBNInsn, RV32RegReg, RV32RegImm, RV32ImmShift, |
| insn_for_mnemonic, |
| ShiftReg) |
| |
| |
| class ADD(RV32RegReg): |
| insn = insn_for_mnemonic('add', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| val2 = model.state.intreg[self.grs2] |
| model.state.intreg[self.grd] = val1 + val2 |
| |
| |
| class ADDI(RV32RegImm): |
| insn = insn_for_mnemonic('addi', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| model.state.intreg[self.grd] = val1 + self.imm |
| |
| |
| class LUI(OTBNInsn): |
| insn = insn_for_mnemonic('lui', 2) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grd = op_vals['grd'] |
| self.imm = op_vals['imm'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| model.state.intreg[self.grd] = (self.imm << 12) |
| |
| |
| class SUB(RV32RegReg): |
| insn = insn_for_mnemonic('sub', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| val2 = model.state.intreg[self.grs2] |
| model.state.intreg[self.grd] = val1 - val2 |
| |
| |
| class SLL(RV32RegReg): |
| insn = insn_for_mnemonic('sll', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| val2 = model.state.intreg[self.grs2] & 0x1f |
| model.state.intreg[self.grd] = val1 << val2 |
| |
| |
| class SLLI(RV32ImmShift): |
| insn = insn_for_mnemonic('slli', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| model.state.intreg[self.grd] = val1 << self.shamt |
| |
| |
| class SRL(RV32RegReg): |
| insn = insn_for_mnemonic('srl', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| val2 = model.state.intreg[self.grs2] & 0x1f |
| model.state.intreg[self.grd] = val1 >> val2 |
| |
| |
| class SRLI(RV32ImmShift): |
| insn = insn_for_mnemonic('srli', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| model.state.intreg[self.grd] = val1 >> self.shamt |
| |
| |
| class SRA(RV32RegReg): |
| insn = insn_for_mnemonic('sra', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| usrc = model.state.intreg[self.grs1].unsigned() |
| shift = model.state.intreg[self.grs2].unsigned() & 0x1f |
| if usrc >> 31: |
| to_clear = 32 - shift |
| sign_mask = (((1 << 32) - 1) >> to_clear) << to_clear |
| else: |
| sign_mask = 0 |
| |
| model.state.intreg[self.grd] = sign_mask | (usrc >> shift) |
| |
| |
| class SRAI(RV32ImmShift): |
| insn = insn_for_mnemonic('srai', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| usrc = model.state.intreg[self.grs1].unsigned() |
| shift = self.shamt |
| if usrc >> 31: |
| to_clear = 32 - shift |
| sign_mask = (((1 << 32) - 1) >> to_clear) << to_clear |
| else: |
| sign_mask = 0 |
| |
| model.state.intreg[self.grd] = sign_mask | (usrc >> shift) |
| |
| |
| class AND(RV32RegReg): |
| insn = insn_for_mnemonic('and', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| val2 = model.state.intreg[self.grs2] |
| model.state.intreg[self.grd] = val1 & val2 |
| |
| |
| class ANDI(RV32RegImm): |
| insn = insn_for_mnemonic('andi', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| model.state.intreg[self.grd] = val1 & self.imm |
| |
| |
| class OR(RV32RegReg): |
| insn = insn_for_mnemonic('or', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| val2 = model.state.intreg[self.grs2] |
| model.state.intreg[self.grd] = val1 | val2 |
| |
| |
| class ORI(RV32RegImm): |
| insn = insn_for_mnemonic('ori', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| model.state.intreg[self.grd] = val1 | self.imm |
| |
| |
| class XOR(RV32RegReg): |
| insn = insn_for_mnemonic('xor', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| val2 = model.state.intreg[self.grs2] |
| model.state.intreg[self.grd] = val1 | val2 |
| |
| |
| class XORI(RV32RegImm): |
| insn = insn_for_mnemonic('xori', 3) |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1] |
| model.state.intreg[self.grd] = val1 | self.imm |
| |
| |
| class LW(OTBNInsn): |
| insn = insn_for_mnemonic('lw', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grd = op_vals['grd'] |
| self.offset = op_vals['offset'] |
| self.grs1 = op_vals['grs1'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| addr = (model.state.intreg[self.grs1] + self.offset).unsigned() |
| data = model.state.memory.lw(addr) |
| model.state.intreg[self.grd] = data |
| |
| |
| class SW(OTBNInsn): |
| insn = insn_for_mnemonic('sw', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grs2 = op_vals['grs2'] |
| self.offset = op_vals['offset'] |
| self.grs1 = op_vals['grs1'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| addr = (model.state.intreg[self.grs1] + self.offset).unsigned() |
| value = model.state.intreg[self.grs2] |
| model.state.memory.sw(addr, value) |
| |
| |
| class BEQ(OTBNInsn): |
| insn = insn_for_mnemonic('beq', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grs1 = op_vals['grs1'] |
| self.grs2 = op_vals['grs2'] |
| self.offset = op_vals['offset'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1].value |
| val2 = model.state.intreg[self.grs2].value |
| if val1 == val2: |
| model.state.pc = model.state.pc + self.offset |
| |
| |
| class BNE(OTBNInsn): |
| insn = insn_for_mnemonic('bne', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grs1 = op_vals['grs1'] |
| self.grs2 = op_vals['grs2'] |
| self.offset = op_vals['offset'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| val1 = model.state.intreg[self.grs1].value |
| val2 = model.state.intreg[self.grs2].value |
| if val1 != val2: |
| model.state.pc = model.state.pc + self.offset |
| |
| |
| class JAL(OTBNInsn): |
| insn = insn_for_mnemonic('jal', 2) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grd = op_vals['grd'] |
| self.offset = op_vals['offset'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| model.state.intreg[self.grd] = model.state.pc + 4 |
| model.state.pc = self.offset |
| |
| |
| class JALR(OTBNInsn): |
| insn = insn_for_mnemonic('jalr', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grd = op_vals['grd'] |
| self.grs1 = op_vals['grs1'] |
| self.offset = op_vals['offset'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| model.state.intreg[self.grd] = model.state.pc + 4 |
| model.state.pc = model.state.intreg[self.grs1] + self.offset |
| |
| |
| class CSRRS(OTBNInsn): |
| insn = insn_for_mnemonic('csrrs', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grd = op_vals['grd'] |
| self.csr = op_vals['csr'] |
| self.grs = op_vals['grs'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| raise NotImplementedError('csrrs.execute') |
| |
| |
| class CSRRW(OTBNInsn): |
| insn = insn_for_mnemonic('csrrw', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grd = op_vals['grd'] |
| self.csr = op_vals['csr'] |
| self.grs = op_vals['grs'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| raise NotImplementedError('csrrw.execute') |
| |
| |
| class ECALL(OTBNInsn): |
| insn = insn_for_mnemonic('ecall', 0) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| pass |
| |
| def execute(self, model: OTBNModel) -> None: |
| model.environment.call(model.state) |
| |
| |
| class LOOP(OTBNInsn): |
| insn = insn_for_mnemonic('loop', 2) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grs = op_vals['grs'] |
| self.bodysize = op_vals['bodysize'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| num_iters = model.state.intreg[self.grs].unsigned() |
| model.state.loop_start(num_iters, self.bodysize) |
| |
| |
| class LOOPI(OTBNInsn): |
| insn = insn_for_mnemonic('loopi', 2) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.iterations = op_vals['iterations'] |
| self.bodysize = op_vals['bodysize'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| model.state.loop_start(self.iterations, self.bodysize) |
| |
| |
| class BNADD(OTBNInsn): |
| insn = insn_for_mnemonic('bn.add', 6) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| self.flag_group = op_vals['flag_group'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1].unsigned()) |
| b_shifted = ShiftReg(int(model.state.wreg[self.wrs2].unsigned()), |
| self.shift_type, self.shift_bytes) |
| (result, flags) = model.add_with_carry(a, b_shifted, 0) |
| model.state.wreg[self.wrd] = result |
| model.state.flags[self.flag_group] = flags |
| |
| |
| class BNADDC(OTBNInsn): |
| insn = insn_for_mnemonic('bn.addc', 6) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| self.flag_group = op_vals['flag_group'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1].unsigned()) |
| b_shifted = ShiftReg(int(model.state.wreg[self.wrs2].unsigned()), |
| self.shift_type, self.shift_bytes) |
| flag_c = model.state.flags[self.flag_group].C |
| (result, flags) = model.add_with_carry(a, b_shifted, flag_c) |
| model.state.wreg[self.wrd] = result |
| model.state.flags[self.flag_group] = flags |
| |
| |
| class BNADDI(OTBNInsn): |
| insn = insn_for_mnemonic('bn.addi', 4) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs = op_vals['wrs'] |
| self.imm = op_vals['imm'] |
| self.flag_group = op_vals['flag_group'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs].unsigned()) |
| b = int(self.imm) |
| (result, flags) = model.add_with_carry(a, b, 0) |
| model.state.wreg[self.wrd] = result |
| model.state.flags[self.flag_group] = flags |
| |
| |
| class BNADDM(OTBNInsn): |
| insn = insn_for_mnemonic('bn.addm', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1].unsigned()) |
| b = int(model.state.wreg[self.wrs2].unsigned()) |
| (result, _) = model.add_with_carry(a, b, 0) |
| if result >= int(model.state.mod): |
| result -= int(model.state.mod) |
| model.state.wreg[self.wrd] = result |
| |
| |
| class BNMULQACC(OTBNInsn): |
| insn = insn_for_mnemonic('bn.mulqacc', 6) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.zero_acc = op_vals['zero_acc'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs1_qwsel = op_vals['wrs1_qwsel'] |
| self.wrs2 = op_vals['wrs2'] |
| self.wrs2_qwsel = op_vals['wrs2_qwsel'] |
| self.acc_shift_imm = op_vals['acc_shift_imm'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a_qw = model.get_wr_quarterword(self.wrs1, self.wrs1_qwsel) |
| b_qw = model.get_wr_quarterword(self.wrs2, self.wrs2_qwsel) |
| |
| mul_res = a_qw * b_qw |
| |
| acc = int(model.state.single_regs['acc']) |
| if self.zero_acc: |
| acc = 0 |
| |
| acc += (mul_res << self.acc_shift_imm) |
| |
| model.state.single_regs['acc'].update(acc) |
| |
| |
| class BNMULQACCWO(OTBNInsn): |
| insn = insn_for_mnemonic('bn.mulqacc.wo', 7) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.zero_acc = op_vals['zero_acc'] |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs1_qwsel = op_vals['wrs1_qwsel'] |
| self.wrs2 = op_vals['wrs2'] |
| self.wrs2_qwsel = op_vals['wrs2_qwsel'] |
| self.acc_shift_imm = op_vals['acc_shift_imm'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a_qw = model.get_wr_quarterword(self.wrs1, self.wrs1_qwsel) |
| b_qw = model.get_wr_quarterword(self.wrs2, self.wrs2_qwsel) |
| |
| mul_res = a_qw * b_qw |
| |
| acc = int(model.state.single_regs['acc']) |
| if self.zero_acc: |
| acc = 0 |
| |
| acc += (mul_res << self.acc_shift_imm) |
| |
| model.state.wreg[self.wrd].set(acc) |
| |
| model.state.single_regs['acc'].update(acc) |
| |
| |
| class BNMULQACCSO(OTBNInsn): |
| insn = insn_for_mnemonic('bn.mulqacc.so', 8) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.zero_acc = op_vals['zero_acc'] |
| self.wrd = op_vals['wrd'] |
| self.wrd_hwsel = op_vals['wrd_hwsel'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs1_qwsel = op_vals['wrs1_qwsel'] |
| self.wrs2 = op_vals['wrs2'] |
| self.wrs2_qwsel = op_vals['wrs2_qwsel'] |
| self.acc_shift_imm = op_vals['acc_shift_imm'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a_qw = model.get_wr_quarterword(self.wrs1, self.wrs1_qwsel) |
| b_qw = model.get_wr_quarterword(self.wrs2, self.wrs2_qwsel) |
| |
| mul_res = a_qw * b_qw |
| |
| acc = int(model.state.single_regs['acc']) |
| if self.zero_acc: |
| acc = 0 |
| |
| acc += (mul_res << self.acc_shift_imm) |
| |
| # set_wr_halfword expects 0 in upper 128 bits |
| acc_lower = acc & ((1 << 128) - 1) |
| model.set_wr_halfword(self.wrd, acc_lower, self.wrd_hwsel) |
| acc = acc >> 128 |
| |
| model.state.single_regs['acc'].update(acc) |
| |
| |
| class BNSUB(OTBNInsn): |
| insn = insn_for_mnemonic('bn.sub', 6) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| self.flag_group = op_vals['flag_group'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1]) |
| b_shifted = ShiftReg(int(model.state.wreg[self.wrs2]), self.shift_type, |
| self.shift_bytes) |
| (result, flags) = model.add_with_carry(a, -b_shifted, 0) |
| model.state.wreg[self.wrd] = result |
| model.state.flags[self.flag_group] = flags |
| |
| |
| class BNSUBB(OTBNInsn): |
| insn = insn_for_mnemonic('bn.subb', 6) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| self.flag_group = op_vals['flag_group'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1]) |
| b_shifted = ShiftReg(int(model.state.wreg[self.wrs2]), self.shift_type, |
| self.shift_bytes) |
| (result, |
| flags) = model.add_with_carry(a, -b_shifted, |
| 1 - model.state.flags[self.flag_group].C) |
| model.state.wreg[self.wrd] = result |
| model.state.flags[self.flag_group] = flags |
| |
| |
| class BNSUBI(OTBNInsn): |
| insn = insn_for_mnemonic('bn.subi', 4) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs = op_vals['wrs'] |
| self.imm = op_vals['imm'] |
| self.flag_group = op_vals['flag_group'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs]) |
| b = int(self.imm) |
| (result, flags) = model.add_with_carry(a, -b, 0) |
| model.state.wreg[self.wrd] = result |
| model.state.flags[self.flag_group] = flags |
| |
| |
| class BNSUBM(OTBNInsn): |
| insn = insn_for_mnemonic('bn.subm', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1]) |
| b = int(model.state.wreg[self.wrs2]) |
| result, _ = model.add_with_carry(a, -b, 0) |
| if result >= model.state.mod: |
| result -= model.state.mod |
| model.state.wreg[self.wrd] = result |
| |
| |
| class BNAND(OTBNInsn): |
| insn = insn_for_mnemonic('bn.and', 5) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| b_shifted = ShiftReg(model.state.wreg[self.wrs2], |
| self.shift_type, self.shift_bytes) |
| a = model.state.wreg[self.wrs1] |
| model.state.wreg[self.wrd] = a & b_shifted |
| |
| |
| class BNOR(OTBNInsn): |
| insn = insn_for_mnemonic('bn.or', 5) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| b_shifted = ShiftReg(model.state.wreg[self.wrs2], |
| self.shift_type, self.shift_bytes) |
| a = model.state.wreg[self.wrs1] |
| model.state.wreg[self.wrd] = a | b_shifted |
| |
| |
| class BNNOT(OTBNInsn): |
| insn = insn_for_mnemonic('bn.not', 4) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs = op_vals['wrs'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| b_shifted = ShiftReg(model.state.wreg[self.wrs], |
| self.shift_type, self.shift_bytes) |
| model.state.wreg[self.wrd] = ~b_shifted |
| |
| |
| class BNXOR(OTBNInsn): |
| insn = insn_for_mnemonic('bn.xor', 5) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| b_shifted = ShiftReg(model.state.wreg[self.wrs2], |
| self.shift_type, self.shift_bytes) |
| a = model.state.wreg[self.wrs1] |
| model.state.wreg[self.wrd] = a ^ b_shifted |
| |
| |
| class BNRSHI(OTBNInsn): |
| insn = insn_for_mnemonic('bn.rshi', 4) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.imm = op_vals['imm'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1]) |
| b = int(model.state.wreg[self.wrs2]) |
| shifted = ((a << 256) | b) >> self.imm |
| model.state.wreg[self.wrd] = shifted & ((1 << 256) - 1) |
| |
| |
| class BNRSEL(OTBNInsn): |
| insn = insn_for_mnemonic('bn.sel', 5) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.flag_group = op_vals['flag_group'] |
| self.flag = op_vals['flag'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| # self.flag gives a number (0-3), which we need to convert to a flag |
| # name for use with BitflagRegister. |
| assert 0 <= self.flag <= 3 |
| flag_name = ['C', 'L', 'M', 'Z'][self.flag] |
| |
| flag_is_set = model.state.flags[self.flag_group].get(flag_name) |
| val = model.state.wreg[self.wrs1 if flag_is_set else self.wrs2] |
| model.state.wreg[self.wrd] = val |
| |
| |
| class BNCMP(OTBNInsn): |
| insn = insn_for_mnemonic('bn.cmp', 5) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| self.flag_group = op_vals['flag_group'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1]) |
| b_shifted = ShiftReg(int(model.state.wreg[self.wrs2]), self.shift_type, |
| self.shift_bytes) |
| (_, flags) = model.add_with_carry(a, -b_shifted, 0) |
| model.state.flags[self.flag_group] = flags |
| |
| |
| class BNCMPB(OTBNInsn): |
| insn = insn_for_mnemonic('bn.cmpb', 5) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrs1 = op_vals['wrs1'] |
| self.wrs2 = op_vals['wrs2'] |
| self.shift_type = op_vals['shift_type'] |
| self.shift_bytes = op_vals['shift_bytes'] |
| self.flag_group = op_vals['flag_group'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| a = int(model.state.wreg[self.wrs1]) |
| b_shifted = ShiftReg(int(model.state.wreg[self.wrs2]), self.shift_type, |
| self.shift_bytes) |
| carry_flag = 1 - model.state.flags[self.flag_group].C |
| (_, flags) = model.add_with_carry(a, -b_shifted, carry_flag) |
| model.state.flags[self.flag_group] = flags |
| |
| |
| class BNLID(OTBNInsn): |
| insn = insn_for_mnemonic('bn.lid', 5) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grd = op_vals['grd'] |
| self.grd_inc = op_vals['grd_inc'] |
| self.offset = op_vals['offset'] |
| self.grs1 = op_vals['grs1'] |
| self.grs1_inc = op_vals['grs1_inc'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| addr = int(model.state.intreg[self.grs1] + int(self.offset)) |
| wrd = int(model.state.intreg[self.grd]) |
| word = model.load_wlen_word_from_memory(addr) |
| model.state.wreg[wrd] = word |
| |
| if self.grd_inc: |
| model.state.intreg[self.grd] += 1 |
| if self.grs1_inc: |
| model.state.intreg[self.grs1] += 32 |
| |
| |
| class BNSID(OTBNInsn): |
| insn = insn_for_mnemonic('bn.sid', 5) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grs2 = op_vals['grs2'] |
| self.grs2_inc = op_vals['grs2_inc'] |
| self.offset = op_vals['offset'] |
| self.grs1 = op_vals['grs1'] |
| self.grs1_inc = op_vals['grs1_inc'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| wrs = int(model.state.intreg[self.grs2]) |
| addr = int(model.state.intreg[self.grs1] + int(self.offset)) |
| word = int(model.state.wreg[wrs]) |
| model.store_wlen_word_to_memory(addr, word) |
| |
| if self.grs2_inc: |
| model.state.intreg[self.grs2] += 1 |
| if self.grs1_inc: |
| model.state.intreg[self.grs1] += 32 |
| |
| |
| class BNMOV(OTBNInsn): |
| insn = insn_for_mnemonic('bn.mov', 2) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wrs = op_vals['wrs'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| model.state.wreg[self.wrd] = model.state.wreg[self.wrs] |
| |
| |
| class BNMOVR(OTBNInsn): |
| insn = insn_for_mnemonic('bn.movr', 4) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.grd = op_vals['grd'] |
| self.grd_inc = op_vals['grd_inc'] |
| self.grs = op_vals['grs'] |
| self.grs_inc = op_vals['grs_inc'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| wrd = int(model.state.intreg[self.grd]) |
| wrs = int(model.state.intreg[self.grs]) |
| model.state.wreg[wrd] = model.state.wreg[wrs] |
| |
| if self.grd_inc: |
| model.state.intreg[self.grd] += 1 |
| if self.grs_inc: |
| model.state.intreg[self.grs] += 1 |
| |
| |
| class BNWSRRS(OTBNInsn): |
| insn = insn_for_mnemonic('bn.wsrrs', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wsr = op_vals['wsr'] |
| self.wrs = op_vals['wrs'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| idx = self.wsr |
| old_val = model.state.wcsr_read(idx) |
| new_val = old_val | model.state.wreg[self.wrs] |
| |
| model.state.wreg[self.wrd] = old_val |
| model.state.wcsr_write(idx, new_val) |
| |
| |
| class BNWSRRW(OTBNInsn): |
| insn = insn_for_mnemonic('bn.wsrrw', 3) |
| |
| def __init__(self, op_vals: Dict[str, int]): |
| super().__init__(op_vals) |
| self.wrd = op_vals['wrd'] |
| self.wsr = op_vals['wsr'] |
| self.wrs = op_vals['wrs'] |
| |
| def execute(self, model: OTBNModel) -> None: |
| idx = self.wsr |
| old_val = model.state.wcsr_read(idx) |
| new_val = model.state.wreg[self.wrs] |
| |
| model.state.wreg[self.wrd] = old_val |
| model.state.wcsr_write(idx, new_val) |
| |
| |
| INSN_CLASSES = [ |
| ADD, ADDI, LUI, SUB, SLL, SLLI, SRL, SRLI, SRA, SRAI, |
| AND, ANDI, OR, ORI, XOR, XORI, |
| LW, SW, |
| BEQ, BNE, JAL, JALR, |
| CSRRS, CSRRW, |
| ECALL, |
| LOOP, LOOPI, |
| |
| BNADD, BNADDC, BNADDI, BNADDM, |
| BNMULQACC, BNMULQACCWO, BNMULQACCSO, |
| BNSUB, BNSUBB, BNSUBI, BNSUBM, |
| BNAND, BNOR, BNNOT, BNXOR, |
| BNRSHI, |
| BNRSEL, |
| BNCMP, BNCMPB, |
| BNLID, BNSID, |
| BNMOV, BNMOVR, |
| BNWSRRS, BNWSRRW |
| ] |