added RV32A extension, only missing LR.W and SC.W

kernel-mode
Anton Lydike 3 years ago
parent 3033eb9985
commit 0c96a87dcb

@ -54,6 +54,11 @@ def name_from_insn(ins: int):
raise RuntimeError(f"Invalid instruction in ebreak/ecall region: {ins:x}") raise RuntimeError(f"Invalid instruction in ebreak/ecall region: {ins:x}")
fun7 = funct7(ins) fun7 = funct7(ins)
if opcode == 0b1011 and fun3 == 0b10:
# ignore the two aq/lr bits located in the fun7 block
# riscemu has no memory reordering, therefore we don't need to look at these bits ever
fun7 = fun7 >> 2
if fun7 in dec: if fun7 in dec:
if opcode == 0x0C or (opcode == 0x04 and fun3 == 5): if opcode == 0x0C or (opcode == 0x04 and fun3 == 5):
dec = dec[fun7] dec = dec[fun7]

@ -112,5 +112,6 @@ INSTRUCTION_ARGS_DECODER: Dict[int, Callable[[int], List[int]]] = {
0x18: decode_b, 0x18: decode_b,
0x19: decode_i, 0x19: decode_i,
0x1b: decode_j, 0x1b: decode_j,
0x1c: decode_i_unsigned 0x1c: decode_i_unsigned,
0b1011: decode_r
} }

@ -67,3 +67,15 @@ RV32[0x0C][5][1] = "divu"
RV32[0x0C][6][1] = "rem" RV32[0x0C][6][1] = "rem"
RV32[0x0C][7][1] = "remu" RV32[0x0C][7][1] = "remu"
# rv32a
RV32[0b1011][0b10][0b00010] = "lr.w"
RV32[0b1011][0b10][0b00011] = "sc.w"
RV32[0b1011][0b10][0b00001] = "amoswap.w"
RV32[0b1011][0b10][0b00000] = "amoadd.w"
RV32[0b1011][0b10][0b00100] = "amoxor.w"
RV32[0b1011][0b10][0b01100] = "amoand.w"
RV32[0b1011][0b10][0b01000] = "amoor.w"
RV32[0b1011][0b10][0b10000] = "amomin.w"
RV32[0b1011][0b10][0b10100] = "amomax.w"
RV32[0b1011][0b10][0b11000] = "amominu.w"
RV32[0b1011][0b10][0b11100] = "amomaxu.w"

@ -0,0 +1,78 @@
from .InstructionSet import InstructionSet, LoadedInstruction
from ..Exceptions import INS_NOT_IMPLEMENTED
from ..helpers import int_from_bytes, int_to_bytes, to_unsigned, to_signed
class RV32A(InstructionSet):
"""
The RV32A instruction set. Currently, load-reserved and store conditionally are not supported
due to limitations in the way the MMU is implemented. Maybe a later implementation will add support
for this?
"""
def instruction_lr_w(self, ins: 'LoadedInstruction'):
INS_NOT_IMPLEMENTED(ins)
def instruction_sc_w(self, ins: 'LoadedInstruction'):
INS_NOT_IMPLEMENTED(ins)
def instruction_amoswap_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
if dest == 'zero':
self.mmu.write(addr, int_to_bytes(addr, 4))
else:
old = int_from_bytes(self.mmu.read(addr, 4))
self.mmu.write(addr, int_to_bytes(val, 4))
self.regs.set(dest, old)
def instruction_amoadd_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
old = int_from_bytes(self.mmu.read(addr, 4))
self.mmu.write(addr, int_to_bytes(old + val, 4))
self.regs.set(dest, old)
def instruction_amoand_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
old = int_from_bytes(self.mmu.read(addr, 4))
self.mmu.write(addr, int_to_bytes(old & val, 4))
self.regs.set(dest, old)
def instruction_amoor_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
old = int_from_bytes(self.mmu.read(addr, 4))
self.mmu.write(addr, int_to_bytes(old | val, 4))
self.regs.set(dest, old)
def instruction_amoxor_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
old = int_from_bytes(self.mmu.read(addr, 4))
self.mmu.write(addr, int_to_bytes(old ^ val, 4))
self.regs.set(dest, old)
def instruction_amomax_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
old = int_from_bytes(self.mmu.read(addr, 4))
self.mmu.write(addr, int_to_bytes(max(old, val), 4))
self.regs.set(dest, old)
def instruction_amomaxu_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
val = to_unsigned(val)
old = int_from_bytes(self.mmu.read(addr, 4), unsigned=True)
self.mmu.write(addr, int_to_bytes(to_signed(max(old, val)), 4))
self.regs.set(dest, old)
def instruction_amomin_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
old = int_from_bytes(self.mmu.read(addr, 4))
self.mmu.write(addr, int_to_bytes(min(old, val), 4))
self.regs.set(dest, old)
def instruction_amominu_w(self, ins: 'LoadedInstruction'):
dest, addr, val = self.parse_rd_rs_rs(ins)
val = to_unsigned(val)
old = int_from_bytes(self.mmu.read(addr, 4), unsigned=True)
self.mmu.write(addr, int_to_bytes(to_signed(min(old, val)), 4))
self.regs.set(dest, old)

@ -9,7 +9,8 @@ This package holds all instruction sets, available to the processor
from .InstructionSet import InstructionSet from .InstructionSet import InstructionSet
from .RV32M import RV32M from .RV32M import RV32M
from .RV32I import RV32I from .RV32I import RV32I
from .RV32A import RV32A
InstructionSetDict = { InstructionSetDict = {
v.__name__: v for v in [RV32I, RV32M] v.__name__: v for v in [RV32I, RV32M, RV32A]
} }

@ -14,7 +14,7 @@ from .PrivMMU import PrivMMU
from ..IO import TextIO from ..IO import TextIO
from .PrivRV32I import PrivRV32I from .PrivRV32I import PrivRV32I
from .privmodes import PrivModes from .privmodes import PrivModes
from ..instructions.RV32M import RV32M from ..instructions import RV32A, RV32M
import json import json
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
@ -48,7 +48,7 @@ class PrivCPU(CPU):
""" """
def __init__(self, conf, mmu: PrivMMU): def __init__(self, conf, mmu: PrivMMU):
super().__init__(conf, [PrivRV32I, RV32M]) super().__init__(conf, [PrivRV32I, RV32M, RV32A])
self.mode: PrivModes = PrivModes.MACHINE self.mode: PrivModes = PrivModes.MACHINE
mmu.set_cpu(self) mmu.set_cpu(self)

Loading…
Cancel
Save