alu.go (3238B)
1 package asm 2 3 //go:generate stringer -output alu_string.go -type=Source,Endianness,ALUOp 4 5 // Source of ALU / ALU64 / Branch operations 6 // 7 // msb lsb 8 // +----+-+---+ 9 // |op |S|cls| 10 // +----+-+---+ 11 type Source uint8 12 13 const sourceMask OpCode = 0x08 14 15 // Source bitmask 16 const ( 17 // InvalidSource is returned by getters when invoked 18 // on non ALU / branch OpCodes. 19 InvalidSource Source = 0xff 20 // ImmSource src is from constant 21 ImmSource Source = 0x00 22 // RegSource src is from register 23 RegSource Source = 0x08 24 ) 25 26 // The Endianness of a byte swap instruction. 27 type Endianness uint8 28 29 const endianMask = sourceMask 30 31 // Endian flags 32 const ( 33 InvalidEndian Endianness = 0xff 34 // Convert to little endian 35 LE Endianness = 0x00 36 // Convert to big endian 37 BE Endianness = 0x08 38 ) 39 40 // ALUOp are ALU / ALU64 operations 41 // 42 // msb lsb 43 // +----+-+---+ 44 // |OP |s|cls| 45 // +----+-+---+ 46 type ALUOp uint8 47 48 const aluMask OpCode = 0xf0 49 50 const ( 51 // InvalidALUOp is returned by getters when invoked 52 // on non ALU OpCodes 53 InvalidALUOp ALUOp = 0xff 54 // Add - addition 55 Add ALUOp = 0x00 56 // Sub - subtraction 57 Sub ALUOp = 0x10 58 // Mul - multiplication 59 Mul ALUOp = 0x20 60 // Div - division 61 Div ALUOp = 0x30 62 // Or - bitwise or 63 Or ALUOp = 0x40 64 // And - bitwise and 65 And ALUOp = 0x50 66 // LSh - bitwise shift left 67 LSh ALUOp = 0x60 68 // RSh - bitwise shift right 69 RSh ALUOp = 0x70 70 // Neg - sign/unsign signing bit 71 Neg ALUOp = 0x80 72 // Mod - modulo 73 Mod ALUOp = 0x90 74 // Xor - bitwise xor 75 Xor ALUOp = 0xa0 76 // Mov - move value from one place to another 77 Mov ALUOp = 0xb0 78 // ArSh - arithmatic shift 79 ArSh ALUOp = 0xc0 80 // Swap - endian conversions 81 Swap ALUOp = 0xd0 82 ) 83 84 // HostTo converts from host to another endianness. 85 func HostTo(endian Endianness, dst Register, size Size) Instruction { 86 var imm int64 87 switch size { 88 case Half: 89 imm = 16 90 case Word: 91 imm = 32 92 case DWord: 93 imm = 64 94 default: 95 return Instruction{OpCode: InvalidOpCode} 96 } 97 98 return Instruction{ 99 OpCode: OpCode(ALUClass).SetALUOp(Swap).SetSource(Source(endian)), 100 Dst: dst, 101 Constant: imm, 102 } 103 } 104 105 // Op returns the OpCode for an ALU operation with a given source. 106 func (op ALUOp) Op(source Source) OpCode { 107 return OpCode(ALU64Class).SetALUOp(op).SetSource(source) 108 } 109 110 // Reg emits `dst (op) src`. 111 func (op ALUOp) Reg(dst, src Register) Instruction { 112 return Instruction{ 113 OpCode: op.Op(RegSource), 114 Dst: dst, 115 Src: src, 116 } 117 } 118 119 // Imm emits `dst (op) value`. 120 func (op ALUOp) Imm(dst Register, value int32) Instruction { 121 return Instruction{ 122 OpCode: op.Op(ImmSource), 123 Dst: dst, 124 Constant: int64(value), 125 } 126 } 127 128 // Op32 returns the OpCode for a 32-bit ALU operation with a given source. 129 func (op ALUOp) Op32(source Source) OpCode { 130 return OpCode(ALUClass).SetALUOp(op).SetSource(source) 131 } 132 133 // Reg32 emits `dst (op) src`, zeroing the upper 32 bit of dst. 134 func (op ALUOp) Reg32(dst, src Register) Instruction { 135 return Instruction{ 136 OpCode: op.Op32(RegSource), 137 Dst: dst, 138 Src: src, 139 } 140 } 141 142 // Imm32 emits `dst (op) value`, zeroing the upper 32 bit of dst. 143 func (op ALUOp) Imm32(dst Register, value int32) Instruction { 144 return Instruction{ 145 OpCode: op.Op32(ImmSource), 146 Dst: dst, 147 Constant: int64(value), 148 } 149 }