sb、lb対応アセンブラ
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 | |
def sb(rs2, imm, rs1) | |
if Register32 === rs1 and Register32 === rs2 and Integer === imm | |
@buf << Insn.new(:S, '0100011', '000', nil, nil, rs1, rs2, imm) | |
else | |
raise | |
end | |
end | |
def lb(rd, imm, rs1) | |
if Register32 === rd and Register32 === rs1 and Integer === imm | |
@buf << Insn.new(:I, '0000011', '000', nil, rd, rs1, nil, imm) | |
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 :S | |
imm = format("%.14b", insn.imm)[2..-1] | |
imm[0..6] + insn.rs2.bit + insn.rs1.bit + insn.funct3 + imm[7..11] + 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