jump.go (3424B)
1 package asm 2 3 //go:generate stringer -output jump_string.go -type=JumpOp 4 5 // JumpOp affect control flow. 6 // 7 // msb lsb 8 // +----+-+---+ 9 // |OP |s|cls| 10 // +----+-+---+ 11 type JumpOp uint8 12 13 const jumpMask OpCode = aluMask 14 15 const ( 16 // InvalidJumpOp is returned by getters when invoked 17 // on non branch OpCodes 18 InvalidJumpOp JumpOp = 0xff 19 // Ja jumps by offset unconditionally 20 Ja JumpOp = 0x00 21 // JEq jumps by offset if r == imm 22 JEq JumpOp = 0x10 23 // JGT jumps by offset if r > imm 24 JGT JumpOp = 0x20 25 // JGE jumps by offset if r >= imm 26 JGE JumpOp = 0x30 27 // JSet jumps by offset if r & imm 28 JSet JumpOp = 0x40 29 // JNE jumps by offset if r != imm 30 JNE JumpOp = 0x50 31 // JSGT jumps by offset if signed r > signed imm 32 JSGT JumpOp = 0x60 33 // JSGE jumps by offset if signed r >= signed imm 34 JSGE JumpOp = 0x70 35 // Call builtin or user defined function from imm 36 Call JumpOp = 0x80 37 // Exit ends execution, with value in r0 38 Exit JumpOp = 0x90 39 // JLT jumps by offset if r < imm 40 JLT JumpOp = 0xa0 41 // JLE jumps by offset if r <= imm 42 JLE JumpOp = 0xb0 43 // JSLT jumps by offset if signed r < signed imm 44 JSLT JumpOp = 0xc0 45 // JSLE jumps by offset if signed r <= signed imm 46 JSLE JumpOp = 0xd0 47 ) 48 49 // Return emits an exit instruction. 50 // 51 // Requires a return value in R0. 52 func Return() Instruction { 53 return Instruction{ 54 OpCode: OpCode(JumpClass).SetJumpOp(Exit), 55 } 56 } 57 58 // Op returns the OpCode for a given jump source. 59 func (op JumpOp) Op(source Source) OpCode { 60 return OpCode(JumpClass).SetJumpOp(op).SetSource(source) 61 } 62 63 // Imm compares 64 bit dst to 64 bit value (sign extended), and adjusts PC by offset if the condition is fulfilled. 64 func (op JumpOp) Imm(dst Register, value int32, label string) Instruction { 65 return Instruction{ 66 OpCode: op.opCode(JumpClass, ImmSource), 67 Dst: dst, 68 Offset: -1, 69 Constant: int64(value), 70 }.WithReference(label) 71 } 72 73 // Imm32 compares 32 bit dst to 32 bit value, and adjusts PC by offset if the condition is fulfilled. 74 // Requires kernel 5.1. 75 func (op JumpOp) Imm32(dst Register, value int32, label string) Instruction { 76 return Instruction{ 77 OpCode: op.opCode(Jump32Class, ImmSource), 78 Dst: dst, 79 Offset: -1, 80 Constant: int64(value), 81 }.WithReference(label) 82 } 83 84 // Reg compares 64 bit dst to 64 bit src, and adjusts PC by offset if the condition is fulfilled. 85 func (op JumpOp) Reg(dst, src Register, label string) Instruction { 86 return Instruction{ 87 OpCode: op.opCode(JumpClass, RegSource), 88 Dst: dst, 89 Src: src, 90 Offset: -1, 91 }.WithReference(label) 92 } 93 94 // Reg32 compares 32 bit dst to 32 bit src, and adjusts PC by offset if the condition is fulfilled. 95 // Requires kernel 5.1. 96 func (op JumpOp) Reg32(dst, src Register, label string) Instruction { 97 return Instruction{ 98 OpCode: op.opCode(Jump32Class, RegSource), 99 Dst: dst, 100 Src: src, 101 Offset: -1, 102 }.WithReference(label) 103 } 104 105 func (op JumpOp) opCode(class Class, source Source) OpCode { 106 if op == Exit || op == Call || op == Ja { 107 return InvalidOpCode 108 } 109 110 return OpCode(class).SetJumpOp(op).SetSource(source) 111 } 112 113 // Label adjusts PC to the address of the label. 114 func (op JumpOp) Label(label string) Instruction { 115 if op == Call { 116 return Instruction{ 117 OpCode: OpCode(JumpClass).SetJumpOp(Call), 118 Src: PseudoCall, 119 Constant: -1, 120 }.WithReference(label) 121 } 122 123 return Instruction{ 124 OpCode: OpCode(JumpClass).SetJumpOp(op), 125 Offset: -1, 126 }.WithReference(label) 127 }