| 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), |
| } |
| } |