summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEkaitz Zarraga <ekaitz@elenq.tech>2021-05-23 22:02:43 +0200
committerEkaitz Zarraga <ekaitz@elenq.tech>2021-05-23 22:02:43 +0200
commita9ecd1abbf4603f4e8d70699cb30374a03b28a7c (patch)
treeab63b398683f9f361e6469c3d6c46c2d501c9f0d
parentd0f52d4f73b802b92c7f7b43e9928e998d92e83c (diff)
Add instructions
-rw-r--r--pysc-v/InstructionSets/RV32I.py245
-rw-r--r--pysc-v/InstructionSets/instructions.py2
2 files changed, 224 insertions, 23 deletions
diff --git a/pysc-v/InstructionSets/RV32I.py b/pysc-v/InstructionSets/RV32I.py
index 53b6859..8950252 100644
--- a/pysc-v/InstructionSets/RV32I.py
+++ b/pysc-v/InstructionSets/RV32I.py
@@ -28,8 +28,8 @@ class I(Instruction):
opcode = None
def __init__(self, rd, rs, imm):
- self.rd = rd
- self.rs = rs
+ self.rd = rd
+ self.rs = rs
self.imm = imm
def compile(self):
@@ -42,58 +42,259 @@ class I(Instruction):
)
class S(Instruction):
- pass
+ funct3 = None
+ opcode = None
+
+ def __init__(self, rs1, rs2, imm):
+ self.rs1 = rs1
+ self.rs2 = rs2
+ self.imm = imm
+
+ def compile(self):
+ imm_0_4 = self.imm & 0x1F
+ imm_5_11 = (self.imm & 0xFE0)>>5
+ return c_uint32(
+ (imm_5_11 << 25) +\
+ (self.rs2 << 20) +\
+ (self.rs1 << 15) +\
+ (self.funct3 << 12) +\
+ (imm_0_4 << 7) +\
+ self.opcode
+ )
class B(Instruction):
- pass
+ funct3 = None
+ opcode = None
+
+ def __init__(self, rs1, rs2, imm):
+ self.rs1 = rs1
+ self.rs2 = rs2
+ self.imm = imm
+
+ def compile(self):
+ # NOTE: The lowest bit of the imm is always 0 because instructions
+ # are at least 16 bits wide, so it's not used, that's why this
+ # instruction looks that weird
+ imm_11 = (self.imm & 0b0100000000000)>>11
+ imm_12 = (self.imm & 0b1000000000000)>>12
+ imm_1_4 = (self.imm & 0b0000000011110)>>1
+ imm_5_10 = (self.imm & 0b0011111100000)>>5
+ return c_uint32(
+ (im_12 << 30) +\
+ (imm_5_10 << 25) +\
+ (self.rs2 << 20) +\
+ (self.rs1 << 15) +\
+ (self.funct3 << 12) +\
+ (imm_1_4 << 8) +\
+ (imm_11 << 7) +\
+ self.opcode
+ )
+
class U(Instruction):
- pass
+ opcode = None
+ def __init__(self, rd, imm):
+ self.rd = rd
+ self.imm = imm
+
+ def compile(self):
+ # NOTE: U Type is for AUIPC and LUI that only use the high part of the
+ # immediate
+ imm_12_32 = (imm & 0xFFFFF000)>>12
+ return c_uint32(
+ (self.imm_12_32 << 12) +\
+ (self.rd << 7) +\
+ self.opcode
+ )
class J(Instruction):
- # TODO check if it's correct
opcode = None
def __init__(self, rd, imm):
- self.rd = rd
+ self.rd = rd
self.imm = imm
def compile(self):
+ # NOTE: Jumps are also weird
+ imm_12_19 = 0x0FF000
+ imm_11 = 0x000800
+ imm_1_10 = 0x0007FE
+ imm_20 = 0x100000
return c_uint32(
- (self.imm << 12) +\
- (self.rd << 7) +\
+ (self.imm_20 << 31) +\
+ (self.imm_1_10 << 21) +\
+ (self.imm_11 << 20) +\
+ (self.imm_12_19 << 12) +\
+ (self.rd << 7) +\
self.opcode
)
-@RV32I.instruction
-class add(R):
- name = "add"
- opcode = 0b0110011
- funct3 = 0b000
- funct7 = 0b0000000
- def execute(self):
- return pc + self.size
@RV32I.instruction
-class addi(I):
- name = "addi"
- opcode = 0b0010011
- funct3 = 0b000
+class lui(U):
+ name = "lui"
+ opcode = 0b0110111
+
+@RV32I.instruction
+class auipc(U):
+ name = "auipc"
+ opcode = 0b0010111
@RV32I.instruction
class jal(J):
name = "jal"
opcode = 0b1101111
- def execute(self):
+ def execute(self, pc):
# TODO
# - Save current pc in rd
# - Make pc from `imm`
# - Return new pc
return pc
+@RV32I.instruction
+class jalr(I):
+ name = "jalr"
+ opcode = 0b1100111
+ funct3 = 0b000
+
+@RV32I.instruction
+class beq(B):
+ name = "beq"
+ opcode = 0b1100011
+ funct3 = 0b000
+
+@RV32I.instruction
+class bne(B):
+ name = "bne"
+ opcode = 0b1100011
+ funct3 = 0b001
+
+@RV32I.instruction
+class blt(B):
+ name = "blt"
+ opcode = 0b1100011
+ funct3 = 0b100
+
+@RV32I.instruction
+class bge(B):
+ name = "bge"
+ opcode = 0b1100011
+ funct3 = 0b101
+
+@RV32I.instruction
+class bltu(B):
+ name = "bltu"
+ opcode = 0b1100011
+ funct3 = 0b110
+
+@RV32I.instruction
+class bgeu(B):
+ name = "bgeu"
+ opcode = 0b1100011
+ funct3 = 0b111
+
+@RV32I.instruction
+class lb(I):
+ name = "lb"
+ opcode = 0b0000011
+ funct3 = 0b000
+
+@RV32I.instruction
+class lh(I):
+ name = "lh"
+ opcode = 0b0000011
+ funct3 = 0b001
+
+@RV32I.instruction
+class lw(I):
+ name = "lw"
+ opcode = 0b0000011
+ funct3 = 0b010
+
+@RV32I.instruction
+class lbu(I):
+ name = "lbu"
+ opcode = 0b0000011
+ funct3 = 0b100
+
+@RV32I.instruction
+class lb(I):
+ name = "lhu"
+ opcode = 0b0000011
+ funct3 = 0b101
+
+@RV32I.instruction
+class sb(S):
+ name = "sb"
+ opcode = 0b010001
+ funct3 = 0b000
+
+@RV32I.instruction
+class sh(S):
+ name = "sh"
+ opcode = 0b010001
+ funct3 = 0b001
+
+@RV32I.instruction
+class sw(S):
+ name = "sw"
+ opcode = 0b010001
+ funct3 = 0b010
+
+@RV32I.instruction
+class addi(I):
+ name = "addi"
+ opcode = 0b0010011
+ funct3 = 0b000
+
+ def execute(self, pc):
+ # TODO
+ return pc + self.size
+
+@RV32I.instruction
+class slti(I):
+ name = "slti"
+ opcode = 0b0010011
+ funct3 = 0b010
+
+@RV32I.instruction
+class sltiu(I):
+ name = "sltiu"
+ opcode = 0b0010011
+ funct3 = 0b011
+
+@RV32I.instruction
+class xori(I):
+ name = "xori"
+ opcode = 0b0010011
+ funct3 = 0b100
+
+@RV32I.instruction
+class ori(I):
+ name = "ori"
+ opcode = 0b0010011
+ funct3 = 0b110
+
+@RV32I.instruction
+class andi(I):
+ name = "andi"
+ opcode = 0b0010011
+ funct3 = 0b111
+
+
+@RV32I.instruction
+class add(R):
+ name = "add"
+ opcode = 0b0110011
+ funct3 = 0b000
+ funct7 = 0b0000000
+
+ def execute(self, pc):
+ # TODO
+ return pc + self.size
@RV32I.pseudoinstruction
class j(J):
diff --git a/pysc-v/InstructionSets/instructions.py b/pysc-v/InstructionSets/instructions.py
index 625226a..00a3146 100644
--- a/pysc-v/InstructionSets/instructions.py
+++ b/pysc-v/InstructionSets/instructions.py
@@ -11,7 +11,7 @@ class Instruction:
# return the binstream of the instruction in a c_uint32
pass
- def execute(self):
+ def execute(self, pc):
# executes the instruction and returns the next program counter
return