github.com/agiledragon/gomonkey/v2@v2.11.1-0.20240427155748-d56c6823ec17/jmp_loong64.go (about)

     1  //go:build loong64
     2  // +build loong64
     3  
     4  package gomonkey
     5  
     6  import "unsafe"
     7  
     8  const (
     9  	REG_R0  uint32 = 0
    10  	REG_R29        = 29
    11  	REG_R30        = 30
    12  )
    13  
    14  const (
    15  	OP_ORI    uint32 = 0x00E << 22
    16  	OP_LU12IW        = 0x00A << 25
    17  	OP_LU32ID        = 0x00B << 25
    18  	OP_LU52ID        = 0x00C << 22
    19  	OP_LDD           = 0x0A3 << 22
    20  	OP_JIRL          = 0x013 << 26
    21  )
    22  
    23  func buildJmpDirective(double uintptr) []byte {
    24  	res := make([]byte, 0, 24)
    25  
    26  	bit11_0 := (double >> 0) & 0xFFF
    27  	bit31_12 := (double >> 12) & 0xFFFFF
    28  	bit51_32 := (double >> 32) & 0xFFFFF
    29  	bit63_52 := (double >> 52) & 0xFFF
    30  
    31  	// lu12i.w r29, bit31_12
    32  	// ori     r29, r29, bit11_0
    33  	// lu32i.d r29, bit51_32
    34  	// lu52i.d r29, bit63_52
    35  	// ld.d,   r30, r29, 0
    36  	// jirl    r0,  r30, 0
    37  	res = append(res, wireup_opc(OP_LU12IW, REG_R29, 0, bit31_12)...)
    38  	res = append(res, wireup_opc(OP_ORI, REG_R29, REG_R29, bit11_0)...)
    39  	res = append(res, wireup_opc(OP_LU32ID, REG_R29, 0, bit51_32)...)
    40  	res = append(res, wireup_opc(OP_LU52ID, REG_R29, REG_R29, bit63_52)...)
    41  	res = append(res, wireup_opc(OP_LDD, REG_R30, REG_R29, 0)...)
    42  	res = append(res, wireup_opc(OP_JIRL, REG_R0, REG_R30, 0)...)
    43  
    44  	return res
    45  }
    46  
    47  func wireup_opc(opc uint32, rd, rj uint32, val uintptr) []byte {
    48  	var m uint32 = 0
    49  
    50  	switch opc {
    51  	case OP_ORI, OP_LU52ID, OP_LDD:
    52  		m |= opc
    53  		m |= (rd & 0x1F) << 0            // rd
    54  		m |= (rj & 0x1F) << 5            // rj
    55  		m |= (uint32(val) & 0xFFF) << 10 // si12
    56  
    57  	case OP_LU12IW, OP_LU32ID:
    58  		m |= opc
    59  		m |= (rd & 0x1F) << 0             // rd
    60  		m |= (uint32(val) & 0xFFFFF) << 5 // si20
    61  
    62  	case OP_JIRL:
    63  		m |= opc
    64  		m |= (rd & 0x1F) << 0             // rd
    65  		m |= (rj & 0x1F) << 5             // rj
    66  		m |= (uint32(val) & 0xFFFF) << 10 // si16
    67  	}
    68  
    69  	res := make([]byte, 4)
    70  	*(*uint32)(unsafe.Pointer(&res[0])) = m
    71  
    72  	return res
    73  }