150 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
package asm
 | 
						|
 | 
						|
//go:generate stringer -output alu_string.go -type=Source,Endianness,ALUOp
 | 
						|
 | 
						|
// Source of ALU / ALU64 / Branch operations
 | 
						|
//
 | 
						|
//    msb      lsb
 | 
						|
//    +----+-+---+
 | 
						|
//    |op  |S|cls|
 | 
						|
//    +----+-+---+
 | 
						|
type Source uint8
 | 
						|
 | 
						|
const sourceMask OpCode = 0x08
 | 
						|
 | 
						|
// Source bitmask
 | 
						|
const (
 | 
						|
	// InvalidSource is returned by getters when invoked
 | 
						|
	// on non ALU / branch OpCodes.
 | 
						|
	InvalidSource Source = 0xff
 | 
						|
	// ImmSource src is from constant
 | 
						|
	ImmSource Source = 0x00
 | 
						|
	// RegSource src is from register
 | 
						|
	RegSource Source = 0x08
 | 
						|
)
 | 
						|
 | 
						|
// The Endianness of a byte swap instruction.
 | 
						|
type Endianness uint8
 | 
						|
 | 
						|
const endianMask = sourceMask
 | 
						|
 | 
						|
// Endian flags
 | 
						|
const (
 | 
						|
	InvalidEndian Endianness = 0xff
 | 
						|
	// Convert to little endian
 | 
						|
	LE Endianness = 0x00
 | 
						|
	// Convert to big endian
 | 
						|
	BE Endianness = 0x08
 | 
						|
)
 | 
						|
 | 
						|
// ALUOp are ALU / ALU64 operations
 | 
						|
//
 | 
						|
//    msb      lsb
 | 
						|
//    +----+-+---+
 | 
						|
//    |OP  |s|cls|
 | 
						|
//    +----+-+---+
 | 
						|
type ALUOp uint8
 | 
						|
 | 
						|
const aluMask OpCode = 0xf0
 | 
						|
 | 
						|
const (
 | 
						|
	// InvalidALUOp is returned by getters when invoked
 | 
						|
	// on non ALU OpCodes
 | 
						|
	InvalidALUOp ALUOp = 0xff
 | 
						|
	// Add - addition
 | 
						|
	Add ALUOp = 0x00
 | 
						|
	// Sub - subtraction
 | 
						|
	Sub ALUOp = 0x10
 | 
						|
	// Mul - multiplication
 | 
						|
	Mul ALUOp = 0x20
 | 
						|
	// Div - division
 | 
						|
	Div ALUOp = 0x30
 | 
						|
	// Or - bitwise or
 | 
						|
	Or ALUOp = 0x40
 | 
						|
	// And - bitwise and
 | 
						|
	And ALUOp = 0x50
 | 
						|
	// LSh - bitwise shift left
 | 
						|
	LSh ALUOp = 0x60
 | 
						|
	// RSh - bitwise shift right
 | 
						|
	RSh ALUOp = 0x70
 | 
						|
	// Neg - sign/unsign signing bit
 | 
						|
	Neg ALUOp = 0x80
 | 
						|
	// Mod - modulo
 | 
						|
	Mod ALUOp = 0x90
 | 
						|
	// Xor - bitwise xor
 | 
						|
	Xor ALUOp = 0xa0
 | 
						|
	// Mov - move value from one place to another
 | 
						|
	Mov ALUOp = 0xb0
 | 
						|
	// ArSh - arithmatic shift
 | 
						|
	ArSh ALUOp = 0xc0
 | 
						|
	// Swap - endian conversions
 | 
						|
	Swap ALUOp = 0xd0
 | 
						|
)
 | 
						|
 | 
						|
// HostTo converts from host to another endianness.
 | 
						|
func HostTo(endian Endianness, dst Register, size Size) Instruction {
 | 
						|
	var imm int64
 | 
						|
	switch size {
 | 
						|
	case Half:
 | 
						|
		imm = 16
 | 
						|
	case Word:
 | 
						|
		imm = 32
 | 
						|
	case DWord:
 | 
						|
		imm = 64
 | 
						|
	default:
 | 
						|
		return Instruction{OpCode: InvalidOpCode}
 | 
						|
	}
 | 
						|
 | 
						|
	return Instruction{
 | 
						|
		OpCode:   OpCode(ALUClass).SetALUOp(Swap).SetSource(Source(endian)),
 | 
						|
		Dst:      dst,
 | 
						|
		Constant: imm,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Op returns the OpCode for an ALU operation with a given source.
 | 
						|
func (op ALUOp) Op(source Source) OpCode {
 | 
						|
	return OpCode(ALU64Class).SetALUOp(op).SetSource(source)
 | 
						|
}
 | 
						|
 | 
						|
// Reg emits `dst (op) src`.
 | 
						|
func (op ALUOp) Reg(dst, src Register) Instruction {
 | 
						|
	return Instruction{
 | 
						|
		OpCode: op.Op(RegSource),
 | 
						|
		Dst:    dst,
 | 
						|
		Src:    src,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Imm emits `dst (op) value`.
 | 
						|
func (op ALUOp) Imm(dst Register, value int32) Instruction {
 | 
						|
	return Instruction{
 | 
						|
		OpCode:   op.Op(ImmSource),
 | 
						|
		Dst:      dst,
 | 
						|
		Constant: int64(value),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Op32 returns the OpCode for a 32-bit ALU operation with a given source.
 | 
						|
func (op ALUOp) Op32(source Source) OpCode {
 | 
						|
	return OpCode(ALUClass).SetALUOp(op).SetSource(source)
 | 
						|
}
 | 
						|
 | 
						|
// Reg32 emits `dst (op) src`, zeroing the upper 32 bit of dst.
 | 
						|
func (op ALUOp) Reg32(dst, src Register) Instruction {
 | 
						|
	return Instruction{
 | 
						|
		OpCode: op.Op32(RegSource),
 | 
						|
		Dst:    dst,
 | 
						|
		Src:    src,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Imm32 emits `dst (op) value`, zeroing the upper 32 bit of dst.
 | 
						|
func (op ALUOp) Imm32(dst Register, value int32) Instruction {
 | 
						|
	return Instruction{
 | 
						|
		OpCode:   op.Op32(ImmSource),
 | 
						|
		Dst:      dst,
 | 
						|
		Constant: int64(value),
 | 
						|
	}
 | 
						|
}
 |