jump.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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 dst to value, and adjusts PC by offset if the condition is fulfilled.
  57. func (op JumpOp) Imm(dst Register, value int32, label string) Instruction {
  58. if op == Exit || op == Call || op == Ja {
  59. return Instruction{OpCode: InvalidOpCode}
  60. }
  61. return Instruction{
  62. OpCode: OpCode(JumpClass).SetJumpOp(op).SetSource(ImmSource),
  63. Dst: dst,
  64. Offset: -1,
  65. Constant: int64(value),
  66. Reference: label,
  67. }
  68. }
  69. // Reg compares dst to src, and adjusts PC by offset if the condition is fulfilled.
  70. func (op JumpOp) Reg(dst, src Register, label string) Instruction {
  71. if op == Exit || op == Call || op == Ja {
  72. return Instruction{OpCode: InvalidOpCode}
  73. }
  74. return Instruction{
  75. OpCode: OpCode(JumpClass).SetJumpOp(op).SetSource(RegSource),
  76. Dst: dst,
  77. Src: src,
  78. Offset: -1,
  79. Reference: label,
  80. }
  81. }
  82. // Label adjusts PC to the address of the label.
  83. func (op JumpOp) Label(label string) Instruction {
  84. if op == Call {
  85. return Instruction{
  86. OpCode: OpCode(JumpClass).SetJumpOp(Call),
  87. Src: R1,
  88. Constant: -1,
  89. Reference: label,
  90. }
  91. }
  92. return Instruction{
  93. OpCode: OpCode(JumpClass).SetJumpOp(op),
  94. Offset: -1,
  95. Reference: label,
  96. }
  97. }