-
-
Save mirichi/1fbefd861df92eb89fe9bc6c87e09d39 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 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