text: """ Thumb instruction definitions """
  
  from ..encoding import Instruction, Operand, Syntax
  from ..token import u16
  from .registers import ArmRegister, LowArmRegister, R7
  from .thumb_relocations import Lit8Relocation, WrapNew11Relocation
  from .thumb_relocations import BImm11Imm6Relocation
  from .thumb_relocations import Rel8Relocation, BlImm11Relocation
  from .isa import thumb_isa, ThumbToken
  
  # pylint: disable=no-member,invalid-name
  
  
  # Instructions:
  
  
  class ThumbInstruction(Instruction):
      """ Base of all thumb instructions.
      """
  
      tokens = [ThumbToken]
      isa = thumb_isa
  
  
  class LongThumbInstruction(ThumbInstruction):
      tokens = [ThumbToken, ThumbToken]
  
  
  class nop_ins(ThumbInstruction):
      syntax = Syntax(["nop"])
  
      def encode(self):
          return bytes()
  
  
  # Memory related
  
  
  class LS_imm5_base(ThumbInstruction):
      """ ??? Rt, [Rn, imm5] """
  
      rn = Operand("rn", LowArmRegister, read=True)
      imm5 = Operand("imm5", int)
  
      def encode(self):
          assert self.imm5 % 4 == 0
          assert self.rn.num < 8
          assert self.rt.num < 8
          Rn = self.rn.num
          Rt = self.rt.num
          imm5 = self.imm5 >> 2
          tokens = self.get_tokens()
          tokens[0][0:3] = Rt
          tokens[0][3:6] = Rn
          tokens[0][6:11] = imm5
          tokens[0][11:16] = self.opcode
          return tokens[0].encode()
  
  
  class Str2(LS_imm5_base):
      rt = Operand("rt", LowArmRegister, read=True)
      syntax = Syntax(
          [
              "str",
              " ",
              rt,
              ",",
              "[",
              LS_imm5_base.rn,
              ",",
              " ",
              LS_imm5_base.imm5,
              "]",
          ]
      )
      opcode = 0xC
  
  
  class Ldr2(LS_imm5_base):
      rt = Operand("rt", LowArmRegister, write=True)
      syntax = Syntax(
          [
              "ldr",
              " ",
              rt,
              ",",
              " ",
              "[",
              LS_imm5_base.rn,
              ",",
              " ",
              LS_imm5_base.imm5,
              "]",
          ]
      )
      opcode = 0xD
  
  
  class LS_byte_imm5_base(ThumbInstruction):
      """ ??? Rt, [Rn, imm5] """
  
      rn = Operand("rn", LowArmRegister, read=True)
      imm5 = Operand("imm5", int)
  
      def encode(self):
          assert self.rn.num < 8
          assert self.rt.num < 8
          Rn = self.rn.num
          Rt = self.rt.num
          imm5 = self.imm5
          tokens = self.get_tokens()
          tokens[0][0:3] = Rt
          tokens[0][3:6] = Rn
          tokens[0][6:11] = imm5
          tokens[0][11:16] = self.opcode
          return tokens[0].encode()
  
  
  class Strb(LS_byte_imm5_base):
      rt = Operand("rt", LowArmRegister, read=True)
      syntax = Syntax(
          [
              "strb",
              " ",
              rt,
              ",",
              " ",
              "[",
              LS_byte_imm5_base.rn,
              ",",
              " ",
              LS_byte_imm5_base.imm5,
              "]",
          ]
      )
      opcode = 0xE
  
  
  class Ldrb(LS_byte_imm5_base):
      rt = Operand("rt", LowArmRegister, write=True)
      syntax = Syntax(
          [
              "ldrb",
              " ",
              rt,
              ",",
              " ",
              "[",
              LS_byte_imm5_base.rn,
              ",",
              " ",
              LS_byte_imm5_base.imm5,
              "]",
          ]
      )
      opcode = 0b01111
  
  
  class Strh(ThumbInstruction):
      """ Strh Rt, [Rn, imm5] """
  
      rt = Operand("rt", LowArmRegister, read=True)
      rn = Operand("rn", LowArmRegister, read=True)
      imm5 = Operand("imm5", int)
      syntax = Syntax(["strh", " ", rt, ",", " ", "[", rn, ",", " ", imm5, "]"])
  
      def encode(self):
          opcode = 0x10
          assert self.rn.num < 8
          assert self.rt.num < 8
          rn = self.rn.num
          rt = self.rt.num
          imm5 = self.imm5 << 1
          tokens = self.get_tokens()
          tokens[0][0:3] = rt
          tokens[0][3:6] = rn
          tokens[0][6:11] = imm5
          tokens[0][11:16] = opcode
          return tokens[0].encode()
  
  
  class Ldrh(ThumbInstruction):
      """ Ldrh Rt, [Rn, imm5] """
  
      rt = Operand("rt", LowArmRegister, write=True)
      rn = Operand("rn", LowArmRegister, read=True)
      imm5 = Operand("imm5", int)
      syntax = Syntax(["ldrh", " ", rt, ",", " ", "[", rn, ",", " ", imm5, "]"])
  
      def encode(self):
          opcode = 0x11
          assert self.rn.num < 8
          assert self.rt.num < 8
          rn = self.rn.num
          rt = self.rt.num
          imm5 = self.imm5
          tokens = self.get_tokens()
          tokens[0][0:3] = rt
          tokens[0][3:6] = rn
          tokens[0][6:11] = imm5
          tokens[0][11:16] = opcode
          return tokens[0].encode()
  
  
  class ls_sp_base_imm8(ThumbInstruction):
      offset = Operand("offset", int)
  
      def encode(self):
          rt = self.rt.num
          assert rt < 8
          imm8 = self.offset >> 2
          assert imm8 < 256
          h = (self.opcode << 8) | (rt << 8) | imm8
          return u16(h)
  
  
  class Ldr3(ThumbInstruction):
      """ ldr Rt, LABEL, load value from pc relative position """
  
      rt = Operand("rt", LowArmRegister, write=True)
      label = Operand("label", str)
      syntax = Syntax(["ldr", " ", rt, ",", " ", label])
  
      def relocations(self):
          return [Lit8Relocation(self.label)]
  
      def encode(self):
          rt = self.rt.num
          assert rt < 8
          imm8 = 0
          h = (0x9 << 11) | (rt << 8) | imm8
          return u16(h)
  
  
  class Ldr1(ls_sp_base_imm8):
      """ ldr Rt, [SP, imm8] """
  
      rt = Operand("rt", LowArmRegister, write=True)
      opcode = 0x98
      syntax = Syntax(
          [
              "ldr",
              " ",
              rt,
              ",",
              " ",
              "[",
              "sp",
              ",",
              " ",
              ls_sp_base_imm8.offset,
              "]",
          ]
      )
  
  
  class Str1(ls_sp_base_imm8):
      """ str Rt, [SP, imm8] """
  
      rt = Operand("rt", LowArmRegister, read=True)
      opcode = 0x90
      syntax = Syntax(
          [
              "str",
              " ",
              rt,
              ",",
              " ",
              "[",
              "sp",
              ",",
              " ",
              ls_sp_base_imm8.offset,
              "]",
          ]
      )
  
  
  class Adr(ThumbInstruction):
      rd = Operand("rd", LowArmRegister, write=True)
      label = Operand("label", str)
      syntax = Syntax(["adr", rd, ",", label])
  
      def relocations(self):
          return [Lit8Relocation(self.label)]
  
      def encode(self):
          tokens = self.get_tokens()
          tokens[0][0:8] = 0  # Filled by linker
          tokens[0][8:11] = self.rd.num
          tokens[0][11:16] = 0b10100
          return tokens[0].encode()
  
  
  class Mov3(ThumbInstruction):
      """ mov Rd, imm8, move immediate value into register """
  
      opcode = 4  # 00100 Rd(3) imm8
      rd = Operand("rd", LowArmRegister, write=True)
      imm = Operand("imm", int)
      syntax = Syntax(["mov", " ", rd, ",", " ", imm])
  
      def encode(self):
          tokens = self.get_tokens()
          rd = self.rd.num
          tokens[0][8:11] = rd
          tokens[0][0:8] = self.imm
          tokens[0][11:16] = self.opcode
          return tokens[0].encode()
  
  
  # Arithmatics:
  
  
  class regregimm3_base(ThumbInstruction):
      rd = Operand("rd", LowArmRegister, write=True)
      rn = Operand("rn", LowArmRegister, read=True)
      imm3 = Operand("imm3", int)
  
      def encode(self):
          assert self.imm3 < 8
          rd = self.rd.num
          tokens = self.get_tokens()
          tokens[0][0:3] = rd
          tokens[0][3:6] = self.rn.num
          tokens[0][6:9] = self.imm3
          tokens[0][9:16] = self.opcode
          return tokens[0].encode()
  
  
  class AddImm(regregimm3_base):
      """ add Rd, Rn, imm3 """
  
      syntax = Syntax(
          [
              "add",
              " ",
              regregimm3_base.rd,
              ",",
              " ",
              regregimm3_base.rn,
              ",",
              regregimm3_base.imm3,
          ]
      )
      opcode = 0b0001110
  
  
  class SubImm(regregimm3_base):
      """ sub Rd, Rn, imm3 """
  
      syntax = Syntax(
          [
              "sub",
              " ",
              regregimm3_base.rd,
              ",",
              " ",
              regregimm3_base.rn,
              ",",
              regregimm3_base.imm3,
          ]
      )
      opcode = 0b0001111
  
  
  class regregreg_base(ThumbInstruction):
      """ ??? Rd, Rn, Rm """
  
      rd = Operand("rd", LowArmRegister, write=True)
      rn = Operand("rn", LowArmRegister, read=True)
      rm = Operand("rm", LowArmRegister, read=True)
  
      def encode(self):
          at = ThumbToken()
          at.rd = self.rd.num
          rn = self.rn.num
          rm = self.rm.num
          at[3:6] = rn
          at[6:9] = rm
          at[9:16] = self.opcode
          return at.encode()
  
  
  class Add3(regregreg_base):
      syntax = Syntax(
          [
              "add",
              " ",
              regregreg_base.rd,
              ",",
              " ",
              regregreg_base.rn,
              ",",
              " ",
              regregreg_base.rm,
          ]
      )
      opcode = 0b0001100
  
  
  class Sub3(regregreg_base):
      syntax = Syntax(
          [
              "sub",
              " ",
              regregreg_base.rd,
              ",",
              " ",
              regregreg_base.rn,
              ",",
              " ",
              regregreg_base.rm,
          ]
      )
      opcode = 0b0001101
  
  
  class Mov2(ThumbInstruction):
      """ mov rd, rm (all registers, also > r7 """
  
      rd = Operand("rd", ArmRegister, write=True)
      rm = Operand("rm", ArmRegister, read=True)
      syntax = Syntax(["mov", " ", rd, ",", " ", rm])
  
      def encode(self):
          tokens = self.get_tokens()
          tokens[0].rd = self.rd.num & 0x7
          D = (self.rd.num >> 3) & 0x1
          Rm = self.rm.num
          opcode = 0b01000110
          tokens[0][8:16] = opcode
          tokens[0][3:7] = Rm
          tokens[0][7] = D
          return tokens[0].encode()
  
  
  class Mul(ThumbInstruction):
      """
          mul Rn, Rdm
  
          multiply Rn and Rm and store the result in Rd
          Rd and Rm are the same register.
      """
  
      rn = Operand("rn", LowArmRegister, read=True)
      rdm = Operand("rdm", LowArmRegister, read=True, write=True)
      syntax = Syntax(["mul", " ", rn, ",", " ", rdm])
  
      def encode(self):
          tokens = self.get_tokens()
          rn = self.rn.num
          tokens[0].rd = self.rdm.num
          opcode = 0b0100001101
          tokens[0][6:16] = opcode
          tokens[0][3:6] = rn
          return tokens[0].encode()
  
  
  class Sdiv(LongThumbInstruction):
      """ Signed division.
          Encoding T1
      """
  
      rd = Operand("rd", ArmRegister, write=True)
      rn = Operand("rn", ArmRegister, read=True)
      rm = Operand("rm", ArmRegister, read=True)
      syntax = Syntax(["sdiv", " ", rd, ",", " ", rn, ",", " ", rm])
  
      def encode(self):
          tokens = self.get_tokens()
          tokens[0][11:16] = 0b11111
          tokens[0][4:11] = 0b0111001
          tokens[0][0:4] = self.rn.num
          tokens[1][12:16] = 0b1111
          tokens[1][8:12] = self.rd.num
          tokens[1][4:8] = 0b1111
          tokens[1][0:4] = self.rm.num
          return tokens[0].encode() + tokens[1].encode()
  
  
  class regreg_base(ThumbInstruction):
      """ ??? Rdn, Rm """
  
      def encode(self):
          tokens = self.get_tokens()
          tokens[0].rd = self.rdn.num
          rm = self.rm.num
          tokens[0][3:6] = rm
          tokens[0][6:16] = self.opcode
          return tokens[0].encode()
  
  
  def make_regreg(mnemonic, opcode):
      rdn = Operand("rdn", LowArmRegister, write=True, read=True)
      rm = Operand("rm", LowArmRegister, read=True)
      syntax = Syntax([mnemonic, rdn, ",", rm])
      members = {"syntax": syntax, "rdn": rdn, "rm": rm, "opcode": opcode}
      return type(mnemonic + "_ins", (regreg_base,), members)
  
  
  And = make_regreg("and", 0b0100000000)
  Orr = make_regreg("orr", 0b0100001100)
  Eor = make_regreg("eor", 0b0100000001)
  Cmp = make_regreg("cmp", 0b0100001010)
  Lsl = make_regreg("lsl", 0b0100000010)
  Lsr = make_regreg("lsr", 0b0100000011)
  Asr = make_regreg("lsr", 0b0100000100)
  Rsb = make_regreg("rsb", 0b0100001001)
  
  
  class Cmp2(ThumbInstruction):
      """ cmp Rn, imm8 """
  
      opcode = 5  # 00101
      rn = Operand("rn", LowArmRegister, read=True)
      imm = Operand("imm", int)
      syntax = Syntax(["cmp", rn, ",", imm])
  
      def encode(self):
          tokens = self.get_tokens()
          tokens[0][0:8] = self.imm
          tokens[0][8:11] = self.rn.num
          tokens[0][11:16] = self.opcode
          return tokens[0].encode()
  
  
  # Jumping:
  
  
  class B(ThumbInstruction):
      target = Operand("target", str)
      syntax = Syntax(["b", " ", target])
  
      def encode(self):
          h = (0b11100 << 11) | 0
          # | 1 # 1 to enable thumb mode
          return u16(h)
  
      def relocations(self):
          return [WrapNew11Relocation(self.target)]
  
  
  class Bw(LongThumbInstruction):
      """ Encoding T4
          Same encoding as Bl, longer jumps are possible with this function!
      """
  
      target = Operand("target", str)
      syntax = Syntax(["bw", " ", target])
  
      def encode(self):
          j1 = 1
          j2 = 1
          tokens = self.get_tokens()
          tokens[0][11:16] = 0b11110
          tokens[1][13] = j1
          tokens[1][11] = j2
          tokens[1][12] = 1
          tokens[1][15] = 1
          return tokens[0].encode() + tokens[1].encode()
  
      def relocations(self):
          return [BlImm11Relocation(self.target)]
  
  
  class Bl(LongThumbInstruction):
      """ Branch with link """
  
      target = Operand("target", str)
      syntax = Syntax(["bl", " ", target])
  
      def encode(self):
          j1 = 1  # TODO: what do these mean?
          j2 = 1
          tokens = self.get_tokens()
          tokens[0][11:16] = 0b11110
          tokens[1][13] = j1
          tokens[1][11] = j2
          tokens[1][12] = 1
          tokens[1][14] = 1
          tokens[1][15] = 1
          return tokens[0].encode() + tokens[1].encode()
  
      def relocations(self):
          return [BlImm11Relocation(self.target)]
  
  
  class Blx(ThumbInstruction):
      """ Branch with link with target in a register """
  
      rm = Operand("rm", ArmRegister, read=True)
      syntax = Syntax(["blx", " ", rm])
  
      def encode(self):
          tokens = self.get_tokens()
          tokens[0][7:16] = 0b010001111
          tokens[0][3:7] = self.rm.num
          tokens[0][0:3] = 0
          return tokens.encode()
  
  
  class cond_base_ins(ThumbInstruction):
      def encode(self):
          imm8 = 0
          h = (0b1101 << 12) | (self.cond << 8) | imm8
          return u16(h)
  
      def relocations(self):
          return [Rel8Relocation(self.target)]
  
  
  def make_cond_branch(mnemonic, cond):
      target = Operand("target", str)
      syntax = Syntax([mnemonic, target])
      members = {"syntax": syntax, "target": target, "cond": cond}
      return type(mnemonic + "_ins", (cond_base_ins,), members)
  
  
  Beq = make_cond_branch("beq", 0)
  Bne = make_cond_branch("bne", 1)
  Blt = make_cond_branch("blt", 0b1011)
  Ble = make_cond_branch("ble", 0b1101)
  Bgt = make_cond_branch("bgt", 0b1100)
  Bge = make_cond_branch("bge", 0b1010)
  
  
  # Long conditional jumps:
  class cond_base_ins_long(LongThumbInstruction):
      """ Encoding T3 """
  
      def encode(self):
          j1 = 0  # TODO: what do these mean?
          j2 = 0
          h1 = (0b11110 << 11) | (self.cond << 6)
          h2 = (0b1000 << 12) | (j1 << 13) | (j2 << 11)
          return u16(h1) + u16(h2)
  
      def relocations(self):
          return [BImm11Imm6Relocation(self.target)]
  
  
  def make_long_cond_branch(mnemonic, cond):
      target = Operand("target", str)
      syntax = Syntax([mnemonic, target])
      members = {"syntax": syntax, "target": target, "cond": cond}
      return type(mnemonic + "_ins", (cond_base_ins_long,), members)
  
  
  Beqw = make_long_cond_branch("beqw", 0)
  Bnew = make_long_cond_branch("bnew", 1)
  Bhsw = make_long_cond_branch("bhsw", 0b0010)  # unsigned higher or same
  Blow = make_long_cond_branch("blow", 0b0011)  # unsigned lower
  Bhiw = make_long_cond_branch("bhiw", 0b1000)  # unsigned higher
  Blsw = make_long_cond_branch("blsw", 0b1001)  # unsigned lower or same
  Bltw = make_long_cond_branch("bltw", 0b1011)  # signed less than
  Blew = make_long_cond_branch("blew", 0b1101)  # signed less than or equal
  Bgtw = make_long_cond_branch("bgtw", 0b1100)  # signed greater than
  Bgew = make_long_cond_branch("bgew", 0b1010)  # signed greater than or equal
  
  
  def push_bit_pos(n):
      if n < 8:
          return n
      elif n == 14:
          return 8
      else:  # pragma: no cover
          raise NotImplementedError("not implemented for {}".format(n))
  
  
  def pop_bit_pos(n):
      if n < 8:
          return n
      elif n == 15:
          return 8
      else:  # pragma: no cover
          raise NotImplementedError("not implemented for {}".format(n))
  
  
  class Push(ThumbInstruction):
      regs = Operand("regs", set)
      syntax = Syntax(["push", " ", regs])
  
      def __repr__(self):
          return "Push {{{}}}".format(self.regs)
  
      def encode(self):
          tokens = self.get_tokens()
          for n in register_numbers(self.regs):
              tokens[0][push_bit_pos(n)] = 1
          tokens[0][9:16] = 0x5A
          return tokens[0].encode()
  
  
  def register_numbers(regs):
      for r in regs:
          yield r.num
  
  
  class Pop(ThumbInstruction):
      regs = Operand("regs", set)
      syntax = Syntax(["pop", " ", regs])
  
      def __repr__(self):
          return "Pop {{{}}}".format(self.regs)
  
      def encode(self):
          tokens = self.get_tokens()
          for n in register_numbers(self.regs):
              tokens[0][pop_bit_pos(n)] = 1
          tokens[0][9:16] = 0x5E
          return tokens[0].encode()
  
  
  class Yield(ThumbInstruction):
      syntax = Syntax(["yield"])
  
      def encode(self):
          return u16(0xBF10)
  
  
  class addspsp_base(ThumbInstruction):
      """ add/sub SP with imm7 << 2 """
  
      imm7 = Operand("imm7", int)
  
      def encode(self):
          assert self.imm7 < 512
          assert self.imm7 % 4 == 0
          return u16((self.opcode << 7) | self.imm7 >> 2)
  
  
  class AddSp(addspsp_base):
      syntax = Syntax(
          ["add", " ", "sp", ",", " ", "sp", ",", " ", addspsp_base.imm7]
      )
      opcode = 0b101100000
  
  
  class SubSp(addspsp_base):
      syntax = Syntax(
          ["sub", " ", "sp", ",", " ", "sp", ",", " ", addspsp_base.imm7]
      )
      opcode = 0b101100001
  
  
  # instruction selector:
  
  
  #############
  # Experiments:
  # stm: MOVI32(MEMI32(reg), reg) 2 'self.emit(Str2, others=[0], src=[c0, c1])'
  # def pattern(*args, **kwargs):
  #    return lambda f: f
  #
  # pattern(
  #    'stm: MOVI32(MEMI32(reg), reg)',
  #    cost=2,
  #    f=lambda c0, c1: emit(Str2, others=[0], src=[c0, c1])
  #    )
  #
  # class Matcher:
  #    @pattern('a', cost=2)
  #    def P1(self):
  #        self.emit()
  #
  #
  # # stm: MOVI32(MEMI32(reg), reg) 2
  # # 'self.emit(Str2, others=[0], src=[c0, c1])'
  # class Str2Pattern:
  #    cost = 2
  #    pattern = 'stm: MOVI32(MEMI32(reg), reg)'
  #
  ###############
  
  
  @thumb_isa.pattern("stm", "JMP", size=2)
  def pattern_jmp(context, tree):
      label = tree.value
      context.emit(Bw(label.name, jumps=[label]))
  
  
  @thumb_isa.pattern("reg", "REGI32", size=0)
  @thumb_isa.pattern("reg", "REGU32", size=0)
  @thumb_isa.pattern("reg", "REGI16", size=0)
  @thumb_isa.pattern("reg", "REGU16", size=0)
  @thumb_isa.pattern("reg", "REGI8", size=0)
  @thumb_isa.pattern("reg", "REGU8", size=0)
  def pattern_reg32(context, tree):
      return tree.value
  
  
  @thumb_isa.pattern("reg", "I32TOU32(reg)", size=0)
  @thumb_isa.pattern("reg", "U32TOI32(reg)", size=0)
  @thumb_isa.pattern("reg", "I32TOI32(reg)", size=0)
  @thumb_isa.pattern("reg", "U32TOU32(reg)", size=0)
  def pattern_i32toi32(context, tree, c0):
      return c0
  
  
  @thumb_isa.pattern("reg", "I16TOI32(reg)", size=0)
  @thumb_isa.pattern("reg", "U16TOI32(reg)", size=0)
  @thumb_isa.pattern("reg", "I16TOU32(reg)", size=0)
  @thumb_isa.pattern("reg", "U16TOU32(reg)", size=0)
  def pattern_i16_to_i32(context, tree, c0):
      # TODO: do something?
      return c0
  
  
  @thumb_isa.pattern("reg", "I32TOI16(reg)", size=0)
  @thumb_isa.pattern("reg", "I32TOU16(reg)", size=0)
  @thumb_isa.pattern("reg", "U32TOI16(reg)", size=0)
  @thumb_isa.pattern("reg", "U32TOU16(reg)", size=0)
  def pattern_i32toi16(context, tree, c0):
      # TODO: do something?
      return c0
  
  
  @thumb_isa.pattern("reg", "I8TOI32(reg)", size=0)
  @thumb_isa.pattern("reg", "U8TOI32(reg)", size=0)
  @thumb_isa.pattern("reg", "I8TOU32(reg)", size=0)
  @thumb_isa.pattern("reg", "U8TOU32(reg)", size=0)
  def pattern_i8toi32(context, tree, c0):
      # TODO: do something?
      return c0
  
  
  @thumb_isa.pattern("reg", "I32TOI8(reg)", size=0)
  @thumb_isa.pattern("reg", "I32TOU8(reg)", size=0)
  @thumb_isa.pattern("reg", "U32TOI8(reg)", size=0)
  @thumb_isa.pattern("reg", "U32TOU8(reg)", size=0)
  def pattern_i32toi8(context, tree, c0):
      # TODO: do something?
      return c0
  
  
  @thumb_isa.pattern("reg", "ADDI32(reg,reg)", size=2)
  @thumb_isa.pattern("reg", "ADDU32(reg,reg)", size=2)
  def pattern_add32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.emit(Add3(d, c0, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "ADDI8(reg,reg)", size=1)
  def pattern_add8(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.emit(Add3(d, c0, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "LABEL", size=2)
  def pattern_label(context, tree):
      d = context.new_reg(LowArmRegister)
      ln = context.frame.add_constant(tree.value)
      context.emit(Ldr3(d, ln))
      return d
  
  
  @thumb_isa.pattern("reg", "FPRELU32", size=9, cycles=9)
  def pattern_fprel32(context, tree):
      d = context.new_reg(LowArmRegister)
      c1 = tree.value.offset
      if c1 >= 0:
          if c1 < 8:
              context.emit(AddImm(d, R7, c1))
          elif c1 < 256:
              d2 = context.new_reg(LowArmRegister)
              context.emit(Mov3(d2, c1))
              context.emit(Add3(d, R7, d2))
          else:
              d2 = context.new_reg(LowArmRegister)
              ln = context.frame.add_constant(c1)
              context.emit(Ldr3(d2, ln))
              context.emit(Add3(d, R7, d2))
      else:
          c1 = -c1
          if c1 < 8:
              context.emit(SubImm(d, R7, c1))
          elif c1 < 256:
              d2 = context.new_reg(LowArmRegister)
              context.emit(Mov3(d2, c1))
              context.emit(Sub3(d, R7, d2))
          else:
              d2 = context.new_reg(LowArmRegister)
              ln = context.frame.add_constant(c1)
              context.emit(Ldr3(d2, ln))
              context.emit(Sub3(d, R7, d2))
      return d
  
  
  @thumb_isa.pattern("reg", "CONSTI32", size=6, cycles=4, energy=4)
  @thumb_isa.pattern("reg", "CONSTU32", size=6, cycles=4, energy=4)
  @thumb_isa.pattern("reg", "CONSTI16", size=6, cycles=4, energy=4)
  @thumb_isa.pattern("reg", "CONSTU16", size=6, cycles=4, energy=4)
  def pattern_const32(context, tree):
      d = context.new_reg(LowArmRegister)
      ln = context.frame.add_constant(tree.value)
      context.emit(Ldr3(d, ln))
      return d
  
  
  @thumb_isa.pattern(
      "reg",
      "CONSTU32",
      size=2,
      cycles=1,
      energy=1,
      condition=lambda x: x.value in range(256),
  )
  @thumb_isa.pattern(
      "reg",
      "CONSTI32",
      size=2,
      cycles=1,
      energy=1,
      condition=lambda x: x.value in range(256),
  )
  def pattern_const32_imm(context, tree):
      """ 8 bit constant loading """
      d = context.new_reg(LowArmRegister)
      context.emit(Mov3(d, tree.value))
      return d
  
  
  @thumb_isa.pattern("reg", "CONSTI8", size=6, cycles=4, energy=4)
  @thumb_isa.pattern("reg", "CONSTU8", size=6, cycles=4, energy=4)
  def pattern_const8(context, tree):
      d = context.new_reg(LowArmRegister)
      ln = context.frame.add_constant(tree.value)
      context.emit(Ldr3(d, ln))
      return d
  
  
  @thumb_isa.pattern(
      "reg",
      "CONSTI8",
      size=2,
      cycles=1,
      energy=1,
      condition=lambda x: x.value in range(256),
  )
  @thumb_isa.pattern(
      "reg",
      "CONSTU8",
      size=2,
      cycles=1,
      energy=1,
      condition=lambda x: x.value in range(256),
  )
  def pattern_const8_imm(context, tree):
      """ 8 bit constant loading """
      d = context.new_reg(LowArmRegister)
      context.emit(Mov3(d, tree.value))
      return d
  
  
  @thumb_isa.pattern("stm", "MOVU32(reg)", size=2)
  @thumb_isa.pattern("stm", "MOVI32(reg)", size=2)
  def pattern_mov32(context, tree, c0):
      reg = tree.value
      context.move(reg, c0)
  
  
  @thumb_isa.pattern("stm", "MOVI16(reg)", size=2)
  @thumb_isa.pattern("stm", "MOVU16(reg)", size=2)
  @thumb_isa.pattern("stm", "MOVI8(reg)", size=2)
  @thumb_isa.pattern("stm", "MOVU8(reg)", size=2)
  def pattern_mov8(context, tree, c0):
      reg = tree.value
      context.move(reg, c0)
  
  
  @thumb_isa.pattern("stm", "CJMPI32(reg,reg)", size=6)
  @thumb_isa.pattern("stm", "CJMPI16(reg,reg)", size=6)
  @thumb_isa.pattern("stm", "CJMPI8(reg,reg)", size=6)
  def pattern_cjmp_signed(context, tree, c0, c1):
      op, yes_label, no_label = tree.value
      opnames = {"<": Bltw, ">": Bgtw, "==": Beqw, "!=": Bnew, ">=": Bgew}
      Bop = opnames[op]
      jmp_ins = Bw(no_label.name, jumps=[no_label])
      context.emit(Cmp(c0, c1))
      context.emit(Bop(yes_label.name, jumps=[yes_label, jmp_ins]))
      context.emit(jmp_ins)
  
  
  @thumb_isa.pattern("stm", "CJMPU32(reg,reg)", size=6)
  @thumb_isa.pattern("stm", "CJMPU16(reg,reg)", size=6)
  @thumb_isa.pattern("stm", "CJMPU8(reg,reg)", size=6)
  def pattern_cjmp_unsigned(context, tree, c0, c1):
      op, yes_label, no_label = tree.value
      opnames = {
          "<": Blow,
          ">": Bhiw,
          "==": Beqw,
          "!=": Bnew,
          "<=": Blsw,
          ">=": Bhsw,
      }
      Bop = opnames[op]
      jmp_ins = Bw(no_label.name, jumps=[no_label])
      context.emit(Cmp(c0, c1))
      context.emit(Bop(yes_label.name, jumps=[yes_label, jmp_ins]))
      context.emit(jmp_ins)
  
  
  @thumb_isa.pattern("mem", "reg", size=0)
  def pattern_mem_reg(context, tree, c0):
      return c0, 0
  
  
  @thumb_isa.pattern("stm", "STRI8(mem,reg)", size=2)
  @thumb_isa.pattern("stm", "STRU8(mem,reg)", size=2)
  def pattern_str8(context, tree, c0, c1):
      rg, offset = c0
      context.emit(Strb(c1, rg, offset))
  
  
  @thumb_isa.pattern("stm", "STRI16(mem,reg)", size=2)
  @thumb_isa.pattern("stm", "STRU16(mem,reg)", size=2)
  def pattern_str16(context, tree, c0, c1):
      rg, offset = c0
      context.emit(Strh(c1, rg, offset))
  
  
  @thumb_isa.pattern("stm", "STRI32(mem, reg)", size=2)
  @thumb_isa.pattern("stm", "STRU32(mem, reg)", size=2)
  def pattern_str32(context, tree, c0, c1):
      rg, offset = c0
      context.emit(Str2(c1, rg, offset))
  
  
  @thumb_isa.pattern("reg", "LDRI8(mem)", size=2)
  @thumb_isa.pattern("reg", "LDRU8(mem)", size=2)
  def pattern_ldr8(context, tree, c0):
      rg, offset = c0
      d = context.new_reg(LowArmRegister)
      context.emit(Ldrb(d, rg, offset))
      return d
  
  
  @thumb_isa.pattern("reg", "LDRI16(mem)", size=2)
  @thumb_isa.pattern("reg", "LDRU16(mem)", size=2)
  def pattern_ldr16(context, tree, c0):
      rg, offset = c0
      d = context.new_reg(LowArmRegister)
      context.emit(Ldrh(d, rg, offset))
      return d
  
  
  @thumb_isa.pattern("reg", "LDRI32(mem)", size=2)
  @thumb_isa.pattern("reg", "LDRU32(mem)", size=2)
  def pattern_ldr32(context, tree, c0):
      rg, offset = c0
      d = context.new_reg(LowArmRegister)
      context.emit(Ldr2(d, rg, offset))
      return d
  
  
  # Arithmatic patterns:
  @thumb_isa.pattern("reg", "SUBU32(reg,reg)", size=2)
  @thumb_isa.pattern("reg", "SUBI32(reg,reg)", size=2)
  def pattern_sub32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.emit(Sub3(d, c0, c1))
      return d
  
  
  @thumb_isa.pattern(
      "reg",
      "SUBI32(reg,CONSTI32)",
      size=2,
      condition=lambda x: x[1].value in range(8),
  )
  def pattern_sub32_imm3(context, tree, c0):
      d = context.new_reg(LowArmRegister)
      c1 = tree[1].value
      context.emit(SubImm(d, c0, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "SUBI8(reg,reg)", size=2)
  def pattern_sub8(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.emit(Sub3(d, c0, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "SHRI8(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHRI16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHRI32(reg, reg)", size=4)
  def pattern_shr_i32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.move(d, c0)
      context.emit(Asr(d, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "SHRU8(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHRU16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHRU32(reg, reg)", size=4)
  def pattern_shr_u32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.move(d, c0)
      context.emit(Lsr(d, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "NEGI32(reg)", size=2)
  @thumb_isa.pattern("reg", "NEGU32(reg)", size=2)
  @thumb_isa.pattern("reg", "NEGI16(reg)", size=2)
  @thumb_isa.pattern("reg", "NEGU16(reg)", size=2)
  @thumb_isa.pattern("reg", "NEGI8(reg)", size=2)
  @thumb_isa.pattern("reg", "NEGU8(reg)", size=2)
  def pattern_neg32(context, tree, c0):
      d = context.new_reg(LowArmRegister)
      context.emit(Rsb(d, c0))
      return d
  
  
  @thumb_isa.pattern("reg", "ORI32(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ORU32(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ORI16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ORU16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ORI8(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ORU8(reg, reg)", size=4)
  def pattern_or32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.move(d, c0)
      context.emit(Orr(d, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "ANDI32(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ANDU32(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ANDI16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ANDU16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ANDI8(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "ANDU8(reg, reg)", size=4)
  def pattern_and32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.move(d, c0)
      context.emit(And(d, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "SHLI32(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHLU32(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHLI16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHLU16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHLI8(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "SHLU8(reg, reg)", size=4)
  def pattern_shl32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.move(d, c0)
      context.emit(Lsl(d, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "MULI32(reg, reg)", size=5)
  @thumb_isa.pattern("reg", "MULU32(reg, reg)", size=5)
  def pattern_mul32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.move(d, c0)
      # Attention: multiply takes the second argument as use and def:
      context.emit(Mul(c1, d))
      return d
  
  
  @thumb_isa.pattern("reg", "DIVI32(reg, reg)", size=10)
  def pattern_div32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.emit(Sdiv(d, c0, c1))
      return d
  
  
  @thumb_isa.pattern("reg", "REMI32(reg, reg)", size=6, cycles=10, energy=5)
  def pattern_rem32(context, tree, c0, c1):
      d2 = context.new_reg(LowArmRegister)
      context.emit(Sdiv(d2, c0, c1))
      # Multiply result by divider:
      context.emit(Mul(c1, d2))
  
      # Substract from divident:
      d = context.new_reg(LowArmRegister)
      context.emit(Sub3(d, c0, d2))
      return d
  
  
  @thumb_isa.pattern("reg", "XORI32(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "XORU32(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "XORI16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "XORU16(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "XORI8(reg, reg)", size=4)
  @thumb_isa.pattern("reg", "XORU8(reg, reg)", size=4)
  def pattern_xor32(context, tree, c0, c1):
      d = context.new_reg(LowArmRegister)
      context.move(d, c0)
      context.emit(Eor(d, c1))
      return d
  