205 lines
4.8 KiB
Go
205 lines
4.8 KiB
Go
|
package asm
|
||
|
|
||
|
//go:generate stringer -output load_store_string.go -type=Mode,Size
|
||
|
|
||
|
// Mode for load and store operations
|
||
|
//
|
||
|
// msb lsb
|
||
|
// +---+--+---+
|
||
|
// |MDE|sz|cls|
|
||
|
// +---+--+---+
|
||
|
type Mode uint8
|
||
|
|
||
|
const modeMask OpCode = 0xe0
|
||
|
|
||
|
const (
|
||
|
// InvalidMode is returned by getters when invoked
|
||
|
// on non load / store OpCodes
|
||
|
InvalidMode Mode = 0xff
|
||
|
// ImmMode - immediate value
|
||
|
ImmMode Mode = 0x00
|
||
|
// AbsMode - immediate value + offset
|
||
|
AbsMode Mode = 0x20
|
||
|
// IndMode - indirect (imm+src)
|
||
|
IndMode Mode = 0x40
|
||
|
// MemMode - load from memory
|
||
|
MemMode Mode = 0x60
|
||
|
// XAddMode - add atomically across processors.
|
||
|
XAddMode Mode = 0xc0
|
||
|
)
|
||
|
|
||
|
// Size of load and store operations
|
||
|
//
|
||
|
// msb lsb
|
||
|
// +---+--+---+
|
||
|
// |mde|SZ|cls|
|
||
|
// +---+--+---+
|
||
|
type Size uint8
|
||
|
|
||
|
const sizeMask OpCode = 0x18
|
||
|
|
||
|
const (
|
||
|
// InvalidSize is returned by getters when invoked
|
||
|
// on non load / store OpCodes
|
||
|
InvalidSize Size = 0xff
|
||
|
// DWord - double word; 64 bits
|
||
|
DWord Size = 0x18
|
||
|
// Word - word; 32 bits
|
||
|
Word Size = 0x00
|
||
|
// Half - half-word; 16 bits
|
||
|
Half Size = 0x08
|
||
|
// Byte - byte; 8 bits
|
||
|
Byte Size = 0x10
|
||
|
)
|
||
|
|
||
|
// Sizeof returns the size in bytes.
|
||
|
func (s Size) Sizeof() int {
|
||
|
switch s {
|
||
|
case DWord:
|
||
|
return 8
|
||
|
case Word:
|
||
|
return 4
|
||
|
case Half:
|
||
|
return 2
|
||
|
case Byte:
|
||
|
return 1
|
||
|
default:
|
||
|
return -1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LoadMemOp returns the OpCode to load a value of given size from memory.
|
||
|
func LoadMemOp(size Size) OpCode {
|
||
|
return OpCode(LdXClass).SetMode(MemMode).SetSize(size)
|
||
|
}
|
||
|
|
||
|
// LoadMem emits `dst = *(size *)(src + offset)`.
|
||
|
func LoadMem(dst, src Register, offset int16, size Size) Instruction {
|
||
|
return Instruction{
|
||
|
OpCode: LoadMemOp(size),
|
||
|
Dst: dst,
|
||
|
Src: src,
|
||
|
Offset: offset,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LoadImmOp returns the OpCode to load an immediate of given size.
|
||
|
//
|
||
|
// As of kernel 4.20, only DWord size is accepted.
|
||
|
func LoadImmOp(size Size) OpCode {
|
||
|
return OpCode(LdClass).SetMode(ImmMode).SetSize(size)
|
||
|
}
|
||
|
|
||
|
// LoadImm emits `dst = (size)value`.
|
||
|
//
|
||
|
// As of kernel 4.20, only DWord size is accepted.
|
||
|
func LoadImm(dst Register, value int64, size Size) Instruction {
|
||
|
return Instruction{
|
||
|
OpCode: LoadImmOp(size),
|
||
|
Dst: dst,
|
||
|
Constant: value,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LoadMapPtr stores a pointer to a map in dst.
|
||
|
func LoadMapPtr(dst Register, fd int) Instruction {
|
||
|
if fd < 0 {
|
||
|
return Instruction{OpCode: InvalidOpCode}
|
||
|
}
|
||
|
|
||
|
return Instruction{
|
||
|
OpCode: LoadImmOp(DWord),
|
||
|
Dst: dst,
|
||
|
Src: PseudoMapFD,
|
||
|
Constant: int64(fd),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LoadMapValue stores a pointer to the value at a certain offset of a map.
|
||
|
func LoadMapValue(dst Register, fd int, offset uint32) Instruction {
|
||
|
if fd < 0 {
|
||
|
return Instruction{OpCode: InvalidOpCode}
|
||
|
}
|
||
|
|
||
|
fdAndOffset := (uint64(offset) << 32) | uint64(uint32(fd))
|
||
|
return Instruction{
|
||
|
OpCode: LoadImmOp(DWord),
|
||
|
Dst: dst,
|
||
|
Src: PseudoMapValue,
|
||
|
Constant: int64(fdAndOffset),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LoadIndOp returns the OpCode for loading a value of given size from an sk_buff.
|
||
|
func LoadIndOp(size Size) OpCode {
|
||
|
return OpCode(LdClass).SetMode(IndMode).SetSize(size)
|
||
|
}
|
||
|
|
||
|
// LoadInd emits `dst = ntoh(*(size *)(((sk_buff *)R6)->data + src + offset))`.
|
||
|
func LoadInd(dst, src Register, offset int32, size Size) Instruction {
|
||
|
return Instruction{
|
||
|
OpCode: LoadIndOp(size),
|
||
|
Dst: dst,
|
||
|
Src: src,
|
||
|
Constant: int64(offset),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LoadAbsOp returns the OpCode for loading a value of given size from an sk_buff.
|
||
|
func LoadAbsOp(size Size) OpCode {
|
||
|
return OpCode(LdClass).SetMode(AbsMode).SetSize(size)
|
||
|
}
|
||
|
|
||
|
// LoadAbs emits `r0 = ntoh(*(size *)(((sk_buff *)R6)->data + offset))`.
|
||
|
func LoadAbs(offset int32, size Size) Instruction {
|
||
|
return Instruction{
|
||
|
OpCode: LoadAbsOp(size),
|
||
|
Dst: R0,
|
||
|
Constant: int64(offset),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// StoreMemOp returns the OpCode for storing a register of given size in memory.
|
||
|
func StoreMemOp(size Size) OpCode {
|
||
|
return OpCode(StXClass).SetMode(MemMode).SetSize(size)
|
||
|
}
|
||
|
|
||
|
// StoreMem emits `*(size *)(dst + offset) = src`
|
||
|
func StoreMem(dst Register, offset int16, src Register, size Size) Instruction {
|
||
|
return Instruction{
|
||
|
OpCode: StoreMemOp(size),
|
||
|
Dst: dst,
|
||
|
Src: src,
|
||
|
Offset: offset,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// StoreImmOp returns the OpCode for storing an immediate of given size in memory.
|
||
|
func StoreImmOp(size Size) OpCode {
|
||
|
return OpCode(StClass).SetMode(MemMode).SetSize(size)
|
||
|
}
|
||
|
|
||
|
// StoreImm emits `*(size *)(dst + offset) = value`.
|
||
|
func StoreImm(dst Register, offset int16, value int64, size Size) Instruction {
|
||
|
return Instruction{
|
||
|
OpCode: StoreImmOp(size),
|
||
|
Dst: dst,
|
||
|
Offset: offset,
|
||
|
Constant: value,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// StoreXAddOp returns the OpCode to atomically add a register to a value in memory.
|
||
|
func StoreXAddOp(size Size) OpCode {
|
||
|
return OpCode(StXClass).SetMode(XAddMode).SetSize(size)
|
||
|
}
|
||
|
|
||
|
// StoreXAdd atomically adds src to *dst.
|
||
|
func StoreXAdd(dst, src Register, size Size) Instruction {
|
||
|
return Instruction{
|
||
|
OpCode: StoreXAddOp(size),
|
||
|
Dst: dst,
|
||
|
Src: src,
|
||
|
}
|
||
|
}
|