risc-vアセンブラ
module RISCVASM | |
# 32bitレジスタ | |
class Register32 | |
end | |
# 32bitレジスタ定義 | |
class X0 < Register32;def bit;'00000';end;end | |
class X1 < Register32;def bit;'00001';end;end | |
class X2 < Register32;def bit;'00010';end;end | |
class X3 < Register32;def bit;'00011';end;end | |
class X4 < Register32;def bit;'00100';end;end | |
class X5 < Register32;def bit;'00101';end;end | |
class X6 < Register32;def bit;'00110';end;end | |
class X7 < Register32;def bit;'00111';end;end | |
class X8 < Register32;def bit;'01000';end;end | |
class X9 < Register32;def bit;'01001';end;end | |
class X10 < Register32;def bit;'01010';end;end | |
class X11 < Register32;def bit;'01011';end;end | |
class X12 < Register32;def bit;'01100';end;end | |
class X13 < Register32;def bit;'01101';end;end | |
class X14 < Register32;def bit;'01110';end;end | |
class X15 < Register32;def bit;'01111';end;end | |
class X16 < Register32;def bit;'10000';end;end | |
class X17 < Register32;def bit;'10001';end;end | |
class X18 < Register32;def bit;'10010';end;end | |
class X19 < Register32;def bit;'10011';end;end | |
class X20 < Register32;def bit;'10100';end;end | |
class X21 < Register32;def bit;'10101';end;end | |
class X22 < Register32;def bit;'10110';end;end | |
class X23 < Register32;def bit;'10111';end;end | |
class X24 < Register32;def bit;'11000';end;end | |
class X25 < Register32;def bit;'11001';end;end | |
class X26 < Register32;def bit;'11010';end;end | |
class X27 < Register32;def bit;'11011';end;end | |
class X28 < Register32;def bit;'11100';end;end | |
class X29 < Register32;def bit;'11101';end;end | |
class X30 < Register32;def bit;'11110';end;end | |
class X31 < Register32;def bit;'11111';end;end | |
# アセンブラクラス | |
class Assembler | |
attr_reader :buf, :labels | |
def initialize | |
@buf = [] | |
@labels = {} | |
@reserve = {} | |
end | |
def x0;X0.new;end | |
def x1;X1.new;end | |
def x2;X2.new;end | |
def x3;X3.new;end | |
def x4;X4.new;end | |
def x5;X5.new;end | |
def x6;X6.new;end | |
def x7;X7.new;end | |
def x8;X8.new;end | |
def x9;X9.new;end | |
def x10;X10.new;end | |
def x11;X11.new;end | |
def x12;X12.new;end | |
def x13;X13.new;end | |
def x14;X14.new;end | |
def x15;X15.new;end | |
def x16;X16.new;end | |
def x17;X17.new;end | |
def x18;X18.new;end | |
def x19;X19.new;end | |
def x20;X20.new;end | |
def x21;X21.new;end | |
def x22;X22.new;end | |
def x23;X23.new;end | |
def x24;X24.new;end | |
def x25;X25.new;end | |
def x26;X26.new;end | |
def x27;X27.new;end | |
def x28;X28.new;end | |
def x29;X29.new;end | |
def x30;X30.new;end | |
def x31;X31.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(x0, x0, 0) | |
end | |
def li(rd, imm) | |
if Register32 === rd and Integer === imm | |
self.lui(rd, imm >> 12) | |
self.ori(rd, rd, imm & 0xfff) | |
else | |
raise | |
end | |
end | |
def mv(rd, rs) | |
if Register32 === rd and Register32 === rs | |
self.addi(rd, rs, 0) | |
else | |
raise | |
end | |
end | |
def lui(rd, imm) | |
if Register32 === rd and Integer === imm | |
@buf << Insn.new(:U, '0110111', nil, nil, rd, nil, nil, imm) | |
else | |
raise | |
end | |
end | |
def auipc(rd, imm) | |
if Register32 === rd and Integer === imm | |
@buf << Insn.new(:U, '0010111', nil, nil, rd, nil, nil, imm) | |
else | |
raise | |
end | |
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 sub(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '000', '0100000', rd, rs1, rs2, nil) | |
else | |
raise | |
end | |
end | |
def andi(rd, rs, imm) | |
if Register32 === rd and Register32 === rs and Integer === imm | |
@buf << Insn.new(:I, '0010011', '111', nil, rd, rs, nil, imm) | |
else | |
raise | |
end | |
end | |
def _and(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '111', '0000000', rd, rs1, rs2, nil) | |
else | |
raise | |
end | |
end | |
def ori(rd, rs, imm) | |
if Register32 === rd and Register32 === rs and Integer === imm | |
@buf << Insn.new(:I, '0010011', '110', nil, rd, rs, nil, imm) | |
else | |
raise | |
end | |
end | |
def _or(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '110', '0000000', rd, rs1, rs2, nil) | |
else | |
raise | |
end | |
end | |
def xori(rd, rs, imm) | |
if Register32 === rd and Register32 === rs and Integer === imm | |
@buf << Insn.new(:I, '0010011', '100', nil, rd, rs, nil, imm) | |
else | |
raise | |
end | |
end | |
def _xor(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '100', '0000000', rd, rs1, rs2, nil) | |
else | |
raise | |
end | |
end | |
def slli(rd, rs, imm) | |
if Register32 === rd and Register32 === rs and Integer === imm | |
@buf << Insn.new(:I, '0010011', '001', nil, rd, rs, nil, imm) | |
else | |
raise | |
end | |
end | |
def sll(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '001', '0000000', rd, rs1, rs2, nil) | |
else | |
raise | |
end | |
end | |
def srli(rd, rs, imm) | |
if Register32 === rd and Register32 === rs and Integer === imm | |
@buf << Insn.new(:I, '0010011', '101', nil, rd, rs, nil, imm) | |
else | |
raise | |
end | |
end | |
def srl(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '101', '0000000', rd, rs1, rs2, nil) | |
else | |
raise | |
end | |
end | |
def srai(rd, rs, imm) | |
if Register32 === rd and Register32 === rs and Integer === imm | |
@buf << Insn.new(:I, '0010011', '101', nil, rd, rs, nil, imm) | |
else | |
raise | |
end | |
end | |
def sra(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '101', '0100000', rd, rs1, rs2, nil) | |
else | |
raise | |
end | |
end | |
def slti(rd, rs, imm) | |
if Register32 === rd and Register32 === rs and Integer === imm | |
@buf << Insn.new(:I, '0010011', '010', nil, rd, rs, nil, imm) | |
else | |
raise | |
end | |
end | |
def slt(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '010', '0000000', rd, rs1, rs2, nil) | |
else | |
raise | |
end | |
end | |
def sltui(rd, rs, imm) | |
if Register32 === rd and Register32 === rs and Integer === imm | |
@buf << Insn.new(:I, '0010011', '011', nil, rd, rs, nil, imm) | |
else | |
raise | |
end | |
end | |
def sltu(rd, rs1, rs2) | |
if Register32 === rd and Register32 === rs1 and Register32 === rs2 | |
@buf << Insn.new(:R, '0110011', '011', '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 sh(rs2, imm, rs1) | |
if Register32 === rs1 and Register32 === rs2 and Integer === imm | |
@buf << Insn.new(:S, '0100011', '001', nil, nil, rs1, rs2, imm) | |
else | |
raise | |
end | |
end | |
def sw(rs2, imm, rs1) | |
if Register32 === rs1 and Register32 === rs2 and Integer === imm | |
@buf << Insn.new(:S, '0100011', '010', 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 | |
def lh(rd, imm, rs1) | |
if Register32 === rd and Register32 === rs1 and Integer === imm | |
@buf << Insn.new(:I, '0000011', '001', nil, rd, rs1, nil, imm) | |
else | |
raise | |
end | |
end | |
def lw(rd, imm, rs1) | |
if Register32 === rd and Register32 === rs1 and Integer === imm | |
@buf << Insn.new(:I, '0000011', '010', nil, rd, rs1, nil, imm) | |
else | |
raise | |
end | |
end | |
def lbu(rd, imm, rs1) | |
if Register32 === rd and Register32 === rs1 and Integer === imm | |
@buf << Insn.new(:I, '0000011', '100', nil, rd, rs1, nil, imm) | |
else | |
raise | |
end | |
end | |
def lhu(rd, imm, rs1) | |
if Register32 === rd and Register32 === rs1 and Integer === imm | |
@buf << Insn.new(:I, '0000011', '101', nil, rd, rs1, nil, imm) | |
else | |
raise | |
end | |
end | |
def beq(rs1, rs2, imm) | |
if Register32 === rs1 and Register32 === rs2 and (Integer === imm or String === imm or Symbol === imm) | |
@buf << Insn.new(:B, '1100011', '000', nil, nil, rs1, rs2, imm) | |
else | |
raise | |
end | |
end | |
def bne(rs1, rs2, imm) | |
if Register32 === rs1 and Register32 === rs2 and (Integer === imm or String === imm or Symbol === imm) | |
@buf << Insn.new(:B, '1100011', '001', nil, nil, rs1, rs2, imm) | |
else | |
raise | |
end | |
end | |
def blt(rs1, rs2, imm) | |
if Register32 === rs1 and Register32 === rs2 and (Integer === imm or String === imm or Symbol === imm) | |
@buf << Insn.new(:B, '1100011', '100', nil, nil, rs1, rs2, imm) | |
else | |
raise | |
end | |
end | |
def bge(rs1, rs2, imm) | |
if Register32 === rs1 and Register32 === rs2 and (Integer === imm or String === imm or Symbol === imm) | |
@buf << Insn.new(:B, '1100011', '101', nil, nil, rs1, rs2, imm) | |
else | |
raise | |
end | |
end | |
def bltu(rs1, rs2, imm) | |
if Register32 === rs1 and Register32 === rs2 and (Integer === imm or String === imm or Symbol === imm) | |
@buf << Insn.new(:B, '1100011', '110', nil, nil, rs1, rs2, imm) | |
else | |
raise | |
end | |
end | |
def bgeu(rs1, rs2, imm) | |
if Register32 === rs1 and Register32 === rs2 and (Integer === imm or String === imm or Symbol === imm) | |
@buf << Insn.new(:B, '1100011', '111', nil, nil, rs1, rs2, imm) | |
else | |
raise | |
end | |
end | |
end | |
def self.asm(datasize, &b) | |
tmp = Assembler.new | |
tmp.instance_eval &b | |
result = 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 :R2 | |
insn.funct7 + insn.rs2.to_s(2).rjust(5,"0") + 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 :B | |
imm = if Integer === insn.imm | |
#[12][10:5] [4:1][11] | |
format("%.14b", insn.imm / 2)[2..-1] | |
else | |
format("%.14b", (tmp.labels[insn.imm.to_s] - i) * 2)[2..-1] | |
end | |
imm[0] + imm[2..7] + insn.rs2.bit + insn.rs1.bit + insn.funct3 + imm[8..11] + imm[1] + insn.opcode | |
when :U | |
#[31:12] | |
addr = if Integer === insn.imm | |
format("%.22b", insn.imm)[-20..-1] | |
end | |
addr + 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 | |
if datasize > result.size | |
result.concat(['00000000000000000000000000010011']*(datasize - result.size)) | |
end | |
return result | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment