diff options
author | Ekaitz Zarraga <ekaitz@elenq.tech> | 2021-05-23 22:02:43 +0200 |
---|---|---|
committer | Ekaitz Zarraga <ekaitz@elenq.tech> | 2021-05-23 22:02:43 +0200 |
commit | a9ecd1abbf4603f4e8d70699cb30374a03b28a7c (patch) | |
tree | ab63b398683f9f361e6469c3d6c46c2d501c9f0d | |
parent | d0f52d4f73b802b92c7f7b43e9928e998d92e83c (diff) |
Add instructions
-rw-r--r-- | pysc-v/InstructionSets/RV32I.py | 245 | ||||
-rw-r--r-- | pysc-v/InstructionSets/instructions.py | 2 |
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 |