Skip to content

Instantly share code, notes, and snippets.

@mirichi

mirichi/riscvasm.rb Secret

Created Dec 16, 2017
Embed
What would you like to do?
RISC-Vアセンブラ
module RISCVASM
# 32bitレジスタ
class Register32
end
# 32bitレジスタ定義
class R0 < Register32;def bit;'00000';end;end
class R1 < Register32;def bit;'00001';end;end
class R2 < Register32;def bit;'00010';end;end
class R3 < Register32;def bit;'00011';end;end
class R4 < Register32;def bit;'00100';end;end
class R5 < Register32;def bit;'00101';end;end
class R6 < Register32;def bit;'00110';end;end
class R7 < Register32;def bit;'00111';end;end
class R8 < Register32;def bit;'01000';end;end
class R9 < Register32;def bit;'01001';end;end
class R10 < Register32;def bit;'01010';end;end
class R11 < Register32;def bit;'01011';end;end
class R12 < Register32;def bit;'01100';end;end
class R13 < Register32;def bit;'01101';end;end
class R14 < Register32;def bit;'01110';end;end
class R15 < Register32;def bit;'01111';end;end
class R16 < Register32;def bit;'10000';end;end
class R17 < Register32;def bit;'10001';end;end
class R18 < Register32;def bit;'10010';end;end
class R19 < Register32;def bit;'10011';end;end
class R20 < Register32;def bit;'10100';end;end
class R21 < Register32;def bit;'10101';end;end
class R22 < Register32;def bit;'10110';end;end
class R23 < Register32;def bit;'10111';end;end
class R24 < Register32;def bit;'11000';end;end
class R25 < Register32;def bit;'11001';end;end
class R26 < Register32;def bit;'11010';end;end
class R27 < Register32;def bit;'11011';end;end
class R28 < Register32;def bit;'11100';end;end
class R29 < Register32;def bit;'11101';end;end
class R30 < Register32;def bit;'11110';end;end
class R31 < Register32;def bit;'11111';end;end
# アセンブラクラス
class Assembler
attr_reader :buf, :labels
def initialize
@buf = []
@labels = {}
@reserve = {}
end
def r0;R0.new;end
def r1;R1.new;end
def r2;R2.new;end
def r3;R3.new;end
def r4;R4.new;end
def r5;R5.new;end
def r6;R6.new;end
def r7;R7.new;end
def r8;R8.new;end
def r9;R9.new;end
def r10;R10.new;end
def r11;R11.new;end
def r12;R12.new;end
def r13;R13.new;end
def r14;R14.new;end
def r15;R15.new;end
def r16;R16.new;end
def r17;R17.new;end
def r18;R18.new;end
def r19;R19.new;end
def r20;R20.new;end
def r21;R21.new;end
def r22;R22.new;end
def r23;R23.new;end
def r24;R24.new;end
def r25;R25.new;end
def r26;R26.new;end
def r27;R27.new;end
def r28;R28.new;end
def r29;R29.new;end
def r30;R30.new;end
def r31;R31.new;end
class Insn < Struct.new(:type, :opcode, :funct3, :funct7, :rd, :rs1, :rs2, :imm);end
def label(name)
raise if @labels.has_key?(name.to_s)
@labels[name.to_s] = @buf.size
end
def nop
self.addi(r0, r0, 0)
end
def jal(rd, imm)
if Register32 === rd and (Integer === imm or String === imm or Symbol === imm)
@buf << Insn.new(:J, '1101111', nil, nil, rd, nil, nil, imm)
else
raise
end
end
def jalr(rd, rs, imm)
if Register32 === rd and Register32 === rs and Integer === imm
@buf << Insn.new(:I, '1100111', '000', nil, rd, rs, nil, imm)
else
raise
end
end
def addi(rd, rs, imm)
if Register32 === rd and Register32 === rs and Integer === imm
@buf << Insn.new(:I, '0010011', '000', nil, rd, rs, nil, imm)
else
raise
end
end
def add(rd, rs1, rs2)
if Register32 === rd and Register32 === rs1 and Register32 === rs2
@buf << Insn.new(:R, '0110011', '000', '0000000', rd, rs1, rs2, nil)
else
raise
end
end
end
def self.asm(&b)
tmp = Assembler.new
tmp.instance_eval &b
tmp.buf.map.with_index do |insn, i|
case insn.type
when :R
insn.funct7 + insn.rs2.bit + insn.rs1.bit + insn.funct3 + insn.rd.bit + insn.opcode
when :I
format("%.14b", insn.imm)[2..-1] + insn.rs1.bit + insn.funct3 + insn.rd.bit + insn.opcode
when :J
#[20][10:1][11][19:12]
addr = if Integer === insn.imm
format("%.22b", insn.imm / 2)[2..-1]
else
format("%.22b", (tmp.labels[insn.imm.to_s] - i) * 2)[2..-1]
end
addr[0] + addr[10..19] + addr[9] + addr[1..8] + insn.rd.bit + insn.opcode
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment