-
-
Save mirichi/447dacb9993b1f504b02d7b9cc9db431 to your computer and use it in GitHub Desktop.
RISC-Vアセンブラ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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