-
Notifications
You must be signed in to change notification settings - Fork 2
Assembler
陳鍾誠 edited this page Dec 28, 2018
·
5 revisions
ADD : R-type
add x9, x20, x21
0 21 20 0 9 15
Func7 rs2 rs1 func3 rd opcode
7bits 5bits 5bits 3bits 5bits 7bits
0000000 10101 10100 000 01001 0110011
LD : S-Type load double words
ld x9, 64(x22)
Immediate[11:5] rs2 rs1 func3 Immediate[4:0] opcode
7bits 5bits 5bits 3bits 5bits 7bits
0000000 10101 10100 000 01001 0000011
SLLI :
SLLI: slli x11, x19, 4 // reg x11 = reg x19 << 4 bits
0000000 shamt rs1 001 rd 0010011
0 4 19 1 11 19
0000000 0100 10011 001 01101 0010011
func InstToBin(inst []string) ([]byte, elf.R_RISCV) {
t := mnem2type[inst[0]]
var op RV_OPCODE_TYPE
if t != RV_INST_PSEUDO {
op = mnem2opcode[inst[0]]
}
var bits uint32
switch t {
case RV_INST_R_TYPE:
rd := reg2bits[inst[1]]
rs1 := reg2bits[inst[2]]
rs2 := reg2bits[inst[3]]
f3 := funct3[inst[0]]
var f7 uint32
if inst[0] == "sub" || inst[0] == "sra" || inst[0] == "sraw" {
f7 = 0x20
}
bits = f7<<25 | rs2<<20 | rs1<<15 | f3<<12 | rd<<7 | uint32(op)
case RV_INST_I_TYPE:
var isop int
if (op == RV_OPCODE_OP_IMM) || (op == RV_OPCODE_OP_IMM_32) {
isop = 1
}
f3 := funct3[inst[0]]
var issh bool
if f3 == 0x01 || f3 == 0x05 {
issh = true
}
rd := reg2bits[inst[1]]
rs1 := reg2bits[inst[3-isop]]
if issh {
shamt, _ := strconv.ParseUint(inst[2+isop], 16, 6)
var f6 uint32
if inst[0] == "srai" || inst[0] == "sraiw" {
f6 = 0x10
} else {
f6 = 0
}
bits = f6<<26 | uint32(shamt)<<20 | rs1<<15 | f3<<12 | rd<<7 | uint32(op)
} else {
imm, _ := strconv.ParseInt(inst[2+isop], 10, 12)
bits = uint32(imm)<<20 | rs1<<15 | f3<<12 | rd<<7 | uint32(op)
}
case RV_INST_S_TYPE:
f3 := funct3[inst[0]]
rs1 := reg2bits[inst[3]]
imm, _ := strconv.ParseInt(inst[2], 10, 12)
rs2 := reg2bits[inst[1]]
bits = uint32(imm) << 20
bits &= 0xfe000000
bits |= (rs2<<20 | rs1<<15 | f3<<12 | (uint32(imm)&0x1f)<<7 | uint32(op))
case RV_INST_B_TYPE:
f3 := funct3[inst[0]]
rs1 := reg2bits[inst[1]]
rs2 := reg2bits[inst[2]]
imm, _ := strconv.ParseUint(inst[3], 16, 12)
fmt.Println(imm)
fmt.Println(imm & 0x800)
imm12 := uint32((imm & 0x800) >> 11)
imm11 := uint32((imm & 0x400) >> 10)
imm10_5 := uint32((imm & 0x3f0) >> 4)
imm4_1 := uint32(imm & 0x00f)
fmt.Println(imm12, imm11, imm10_5, imm4_1)
bits = imm12<<31 | imm10_5<<25 | rs2<<20 | rs1<<15 | f3<<12 | imm4_1<<8 | imm11<<7 | uint32(op)
case RV_INST_U_TYPE:
rd := reg2bits[inst[1]]
imm, _ := strconv.ParseUint(inst[2], 16, 20)
bits = uint32(imm)<<12 | rd<<7 | uint32(op)
case RV_INST_J_TYPE:
case RV_INST_NONE:
bits |= uint32(op)
case RV_INST_PSEUDO:
if inst[0] == "call" {
ra, _ := InstToBin([]string{"auipc", "ra", "0"})
rb, _ := InstToBin([]string{"jalr", "ra", "0", "ra"})
return append(ra, rb...), elf.R_RISCV_CALL
}
}
ret := make([]byte, 4)
binary.LittleEndian.PutUint32(ret, bits)
return ret, elf.R_RISCV_NONE
}