jump.go 3.3 KB

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