Skip to content

Commit

Permalink
support riscv64
Browse files Browse the repository at this point in the history
  • Loading branch information
agiledragon committed Feb 11, 2025
1 parent dde4dd3 commit 2ba0792
Showing 1 changed file with 105 additions and 0 deletions.
105 changes: 105 additions & 0 deletions jmp_riscv64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package gomonkey

import (
"encoding/binary"
)

// buildJmpDirective 为 riscv64 架构生成一段跳转指令,
// 将传入的 64 位地址加载到寄存器 x6(t1)中,
// 然后执行 JALR x0, 0(x6) 实现无条件跳转。
func buildJmpDirective(double uintptr) []byte {
var res []byte
// 将地址转换为 64 位无符号整数
d := uint64(double)
// 将 64 位地址拆分成若干部分:
// imm0: 位 [7:0]
// imm1: 位 [19:8] (12 位)
// imm2: 位 [31:20] (12 位)
// imm3: 位 [43:32] (12 位)
// imm4: 位 [63:44] (20 位)
imm0 := d & 0xff
imm1 := (d >> 8) & 0xfff
imm2 := (d >> 20) & 0xfff
imm3 := (d >> 32) & 0xfff
imm4 := (d >> 44) & 0xfffff

// 依次生成指令:
// 1. LUI x6, imm4 // 将最高 20 位加载到 x6
res = append(res, encodeLUI(6, uint32(imm4))...)
// 2. ADDI x6, x6, imm3 // 加载接下来的 12 位
res = append(res, encodeADDI(6, 6, int32(imm3))...)
// 3. SLLI x6, x6, 12 // 左移 12 位
res = append(res, encodeSLLI(6, 6, 12)...)
// 4. ADDI x6, x6, imm2 // 加载接下来的 12 位
res = append(res, encodeADDI(6, 6, int32(imm2))...)
// 5. SLLI x6, x6, 12 // 再次左移 12 位
res = append(res, encodeSLLI(6, 6, 12)...)
// 6. ADDI x6, x6, imm1 // 加载接下来的 12 位
res = append(res, encodeADDI(6, 6, int32(imm1))...)
// 7. SLLI x6, x6, 8 // 左移 8 位
res = append(res, encodeSLLI(6, 6, 8)...)
// 8. ORI x6, x6, imm0 // 最后加载最低 8 位
res = append(res, encodeORI(6, 6, int32(imm0))...)
// 9. JALR x0, 0(x6) // 跳转到 x6 指定的地址
res = append(res, encodeJALR(0, 6, 0)...)

return res
}

// 以下辅助函数生成各条指令的机器码,均返回 4 字节小端表示。

// LUI 指令格式:
// 31 12 11 7 6 0
// [ imm[31:12] ] [ rd ] [ opcode ]
// opcode LUI 为 0x37。
func encodeLUI(rd int, imm20 uint32) []byte {
inst := (imm20 << 12) | (uint32(rd) << 7) | 0x37
res := make([]byte, 4)
binary.LittleEndian.PutUint32(res, inst)
return res
}

// ADDI 指令格式(用于加载 12 位立即数):
// 31 20 19 15 14 12 11 7 6 0
// [ imm[11:0] ] [ rs1 ] [funct3] [ rd ] [ opcode ]
// opcode ADDI 为 0x13,funct3 为 0。
func encodeADDI(rd, rs1 int, imm int32) []byte {
inst := ((uint32(imm) & 0xfff) << 20) | (uint32(rs1) << 15) | (uint32(rd) << 7) | 0x13
res := make([]byte, 4)
binary.LittleEndian.PutUint32(res, inst)
return res
}

// SLLI 指令格式:
// 31 26 25 20 19 15 14 12 11 7 6 0
// [ 0 ] [ shamt ] [ rs1 ] [funct3] [ rd ] [ opcode ]
// opcode 为 0x13,funct3 为 1。
func encodeSLLI(rd, rs1, shamt int) []byte {
inst := (uint32(shamt) << 20) | (uint32(rs1) << 15) | (1 << 12) | (uint32(rd) << 7) | 0x13
res := make([]byte, 4)
binary.LittleEndian.PutUint32(res, inst)
return res
}

// ORI 指令格式:
// 31 20 19 15 14 12 11 7 6 0
// [ imm[11:0] ] [ rs1 ] [funct3] [ rd ] [ opcode ]
// opcode 为 0x13,funct3 为 6。
func encodeORI(rd, rs1 int, imm int32) []byte {
inst := ((uint32(imm) & 0xfff) << 20) | (uint32(rs1) << 15) | (6 << 12) | (uint32(rd) << 7) | 0x13
res := make([]byte, 4)
binary.LittleEndian.PutUint32(res, inst)
return res
}

// JALR 指令格式:
// 31 20 19 15 14 12 11 7 6 0
// [ imm[11:0] ] [ rs1 ] [funct3] [ rd ] [ opcode ]
// opcode 为 0x67,funct3 为 0。
// JALR x0, 0(x6) 用于无条件跳转。
func encodeJALR(rd, rs1 int, imm int32) []byte {
inst := ((uint32(imm) & 0xfff) << 20) | (uint32(rs1) << 15) | (uint32(rd) << 7) | 0x67
res := make([]byte, 4)
binary.LittleEndian.PutUint32(res, inst)
return res
}

0 comments on commit 2ba0792

Please sign in to comment.