Package jnr.x86asm

Examples of jnr.x86asm.HINT


      {
        Label label = (Label) o1;
       
        boolean isShortJump = (code.ordinal() >= INST_J_SHORT.ordinal() && code.ordinal() <= INST_JMP_SHORT.ordinal());

        final HINT hint = o2.isImm() ? HINT.valueOf((int) ((Immediate) o2).value()) : HINT.HINT_NONE;
       

        // Emit jump hint if configured for that.
        if (hint == HINT_TAKEN || hint == HINT_NOT_TAKEN
            && (_properties & (1 << PROPERTY_X86_JCC_HINTS)) != 0)
        {
            _emitByte(hint.value());
        }

        if (label.isBound())
        {
          final int rel8_size = 2;
          final int rel32_size = 6;
          final int offs = label.position() - offset();

          assert(offs <= 0);

          if (isInt8(offs - rel8_size))
          {
            _emitByte(0x70 | (id.opCode1 & 0xff));
            _emitByte((byte) (offs - rel8_size));
          }
          else
          {
            if (isShortJump && _logger != null)
            {
              _logger.log("; WARNING: Emitting long conditional jump, but short jump instruction forced!");
            }

            _emitByte(0x0F);
            _emitByte(0x80 | (id.opCode1 & 0xff));
            _emitInt32((int) (offs - rel32_size));
          }
        }
        else
        {
          if (isShortJump)
          {
            _emitByte(0x70 | (id.opCode1 & 0xff));
            _emitDisplacement(label, -1, 1);
          }
          else
          {
            _emitByte(0x0F);
            _emitByte(0x80 | (id.opCode1 & 0xff));
            _emitDisplacement(label, -4, 4);
          }
        }
        return;
      }

      break;
    }

    case I_JMP:
    {
      if (o1.isRegMem())
      {
        final Operand dst = o1;

        _emitX86RM(0xFF,
          false,
          false, 4, dst,
          0);
        return;
      }

      if (o1.isImm())
      {
        final Immediate imm = (Immediate) o1;
        _emitByte(0xE9);
        _emitJmpOrCallReloc(I_JMP, imm.value());
        return;
      }

      if (o1.isLabel())
      {
        Label label = (Label) o1;
        boolean isShortJump = (code == INST_JMP_SHORT);

        if (label.isBound())
        {
          final int rel8_size = 2;
          final int rel32_size = 5;
          final int offs = label.position() - offset();

          if (isInt8(offs - rel8_size))
          {
            _emitByte(0xEB);
            _emitByte((byte) (offs - rel8_size));
          }
          else
          {
            if (isShortJump && _logger != null)
            {
              _logger.log("; WARNING: Emitting long jump, but short jump instruction forced!");
            }

            _emitByte(0xE9);
            _emitInt32((int)(offs - rel32_size));
          }
        }
        else
        {
          if (isShortJump)
          {
            _emitByte(0xEB);
            _emitDisplacement(label, -1, 1);
          }
          else
          {
            _emitByte(0xE9);
            _emitDisplacement(label, -4, 4);
          }
        }
        return;
      }

      break;
    }

    case I_LEA:
    {
      if (o1.isReg() && o2.isMem())
      {
        final Register dst = (Register) o1;
        final Mem src = (Mem) o2;
        _emitX86RM(0x8D,
          dst.isRegType(REG_GPW),
          dst.isRegType(REG_GPQ), dst.code(), src,
          0);
        return;
      }

      break;
    }

    case I_M:
    {
      if (o1.isMem())
      {
        _emitX86RM(id.opCode1, false, (byte) id.opCode2, id.opCodeR, (Mem) o1, 0);
        return;
      }
      break;
    }

    case I_MOV:
    {
      final Operand dst = o1;
      final Operand src = o2;

      switch (dst.op() << 4 | src.op())
      {
        // Reg <- Reg/Mem
        case (OP_REG << 4) | OP_REG:
        {
          assert(src.isRegType(REG_GPB) || src.isRegType(REG_GPW) ||
                        src.isRegType(REG_GPD) || src.isRegType(REG_GPQ));
          // ... fall through ...
        }
        case (OP_REG << 4) | OP_MEM:
        {
          assert(dst.isRegType(REG_GPB) || dst.isRegType(REG_GPW) ||
                        dst.isRegType(REG_GPD) || dst.isRegType(REG_GPQ));

          _emitX86RM(0x0000008A + intValue(!dst.isRegType(REG_GPB)),
            dst.isRegType(REG_GPW),
            dst.isRegType(REG_GPQ),
            ((Register) dst).code(),
            src,
            0);
          return;
        }

        // Reg <- Imm
        case (OP_REG << 4) | OP_IMM:
        {
          final Immediate isrc = (Immediate) o2;

          // in 64 bit mode immediate can be 8 byte long!
          int immSize = dst.size();

          // Optimize instruction size by using 32 bit immediate if value can
          // fit to it
          if (is64() && immSize == 8 && isInt32(isrc.value()) && isrc.relocMode() == RELOC_NONE)
          {
            _emitX86RM(0xC7,
              dst.isRegType(REG_GPW),
              dst.isRegType(REG_GPQ),
              0,
              dst,
              0);
            immSize = 4;
          }
          else
          {
            _emitX86Inl((dst.size() == 1 ? 0xB0 : 0xB8),
              dst.isRegType(REG_GPW),
              dst.isRegType(REG_GPQ),
              ((Register) dst).code());
          }

          _emitImmediate(isrc, immSize);
          return;
        }

        // Mem <- Reg
        case (OP_MEM << 4) | OP_REG:
        {
          assert(src.isRegType(REG_GPB) || src.isRegType(REG_GPW) ||
                        src.isRegType(REG_GPD) || src.isRegType(REG_GPQ));

          _emitX86RM(0x88 + intValue(!src.isRegType(REG_GPB)),
            src.isRegType(REG_GPW),
            src.isRegType(REG_GPQ),
            ((Register) src).code(),
            dst,
            0);
          return;
        }

        // Mem <- Imm
        case (OP_MEM << 4) | OP_IMM:
        {
          int immSize = dst.size() <= 4 ? dst.size() : 4;

          _emitX86RM(0xC6 + intValue(dst.size() != 1),
            dst.size() == 2,
            dst.size() == 8,
            0,
            dst,
            immSize);
          _emitImmediate((Immediate) src,
            immSize);
          return;
        }
      }

      break;
    }

    case I_MOV_PTR:
    {
      if ((o1.isReg() && o2.isImm()) || (o1.isImm() && o2.isReg()))
      {
        boolean reverse = o1.op() == OP_REG;
        int opCode = !reverse ? 0xA0 : 0xA2;
        final Register reg = (Register)(!reverse ? o1 : o2);
        final Immediate imm = (Immediate)(!reverse ? o2 : o1);

        if (reg.index() != 0) throw new IllegalStateException("reg.index() != 0");

        if (reg.isRegType(REG_GPW)) _emitByte(0x66);

        if (is64()) {
            _emitRexR(reg.size() == 8, 0, 0);
        }

        _emitByte(opCode + intValue(reg.size() != 1));
        _emitImmediate(imm, is64() ? 8 : 4);
        return;
      }

      break;
    }

    case I_MOVSX_MOVZX:
    {
      if (o1.isReg() && o2.isRegMem())
      {
        final Register dst = (Register)(o1);
        final Operand src = (o2);

        if (dst.isRegType(REG_GPB)) throw new IllegalArgumentException("not gpb");
        if (src.size() != 1 && src.size() != 2) throw new IllegalArgumentException("src.size !=1 && src.size != 2");
        if (src.size() == 2 && dst.isRegType(REG_GPW)) throw new IllegalArgumentException("not gpw");

        _emitX86RM(id.opCode1 + intValue(src.size() != 1),
          dst.isRegType(REG_GPW),
          dst.isRegType(REG_GPQ),
          dst.code(),
          src,
          0);
        return;
      }

      break;
    }

    case I_MOVSXD:
    {
        if (!is64()) {
            throw new IllegalStateException("illegal instruction");
        }
      if (o1.isReg() && o2.isRegMem())
      {
        final Register dst = (Register)(o1);
        final Operand src = (o2);
        _emitX86RM(0x00000063,
          false,
          1, dst.code(), src,
          0);
        return;
      }

      break;
    }


    case I_PUSH:
    {
      // This section is only for immediates, memory/register operands are handled in I_POP.
      if (o1.isImm())
      {
        final Immediate imm = (Immediate)(o1);

        if (isInt8(imm.value()) && imm.relocMode() == RELOC_NONE)
        {
          _emitByte(0x6A);
          _emitImmediate(imm, 1);
        }
        else
        {
          _emitByte(0x68);
          _emitImmediate(imm, 4);
        }
        return;
      }

      // ... goto I_POP ...
    }

    case I_POP:
    {
      if (o1.isReg())
      {
        assert(o1.isRegType(REG_GPW) || o1.isRegType(is64() ? REG_GPQ : REG_GPD));
        _emitX86Inl(id.opCode1, o1.isRegType(REG_GPW), 0, ((Register) o1).code());
        return;
      }

      if (o1.isMem())
      {
        _emitX86RM(id.opCode2, o1.size() == 2, 0, id.opCodeR, (o1), 0);
        return;
      }

      break;
    }

    case I_R_RM:
    {
      if (o1.isReg() && o2.isRegMem())
      {
        final Register dst = (Register)(o1);
        assert(dst.type() != REG_GPB);
        final Operand src = (o2);

        _emitX86RM(id.opCode1,
          dst.type() == REG_GPW,
          dst.type() == REG_GPQ, dst.code(), src,
          0);
        return;
      }

      break;
    }

    case I_RM_B:
    {
      if (o1.isRegMem())
      {
        final Operand op = (o1);
        _emitX86RM(id.opCode1, false, false, 0, op, 0);
        return;
      }

      break;
    }

    case I_RM:
    {
      if (o1.isRegMem())
      {
        final Operand op = (o1);
        _emitX86RM(id.opCode1 + intValue(op.size() != 1),
          op.size() == 2,
          op.size() == 8, id.opCodeR, op,
          0);
        return;
      }

      break;
    }

    case I_RM_R:
    {
      if (o1.isRegMem() && o2.isReg())
      {
        final Operand dst = (o1);
        final Register src = (Register)(o2);
        _emitX86RM(id.opCode1 + intValue(src.type() != REG_GPB),
          src.type() == REG_GPW,
          src.type() == REG_GPQ, src.code(), dst,
          0);
        return;
      }

      break;
    }

    case I_RET:
    {
      if (o1.isNone())
      {
        _emitByte(0xC3);
        return;
      }
      else if (o1.isImm())
      {
        final Immediate imm = (Immediate)(o1);
        assert(isUInt16(imm.value()));

        if (imm.value() == 0 && imm.relocMode() == RELOC_NONE)
        {
          _emitByte(0xC3);
        }
        else
        {
          _emitByte(0xC2);
          _emitImmediate(imm, 2);
        }
        return;
      }

      break;
    }

    case I_ROT:
    {
      if (o1.isRegMem() && (o2.isRegCode(REG_CL) || o2.isImm()))
      {
        // generate opcode. For these operations is base 0xC0 or 0xD0.
        boolean useImm8 = (o2.isImm() &&
                       (((Immediate) o2).value() != 1 ||
                        ((Immediate) o2).relocMode() != RELOC_NONE));
        int opCode = useImm8 ? 0xC0 : 0xD0;

        // size and operand type modifies the opcode
        if (o1.size() != 1) opCode |= 0x01;
        if (o2.op() == OP_REG) opCode |= 0x02;

        _emitX86RM(opCode,
          o1.size() == 2,
          o1.size() == 8,
          id.opCodeR, (o1),
          intValue(useImm8));
        if (useImm8)
          _emitImmediate((Immediate)(o2), 1);
        return;
      }

      break;
    }

    case I_SHLD_SHRD:
    {
      if (o1.isRegMem() && o2.isReg() && (o3.isImm() || (o3.isReg() && o3.isRegCode(REG_CL))))
      {
        final Operand dst = (o1);
        final Register src1 = (Register)(o2);
        final Operand src2 = (o3);

        assert(dst.size() == src1.size());

        _emitX86RM(id.opCode1 + intValue(src2.isReg()),
          src1.isRegType(REG_GPW),
          src1.isRegType(REG_GPQ),
          src1.code(), dst,
          intValue(src2.isImm()));
        if (src2.isImm())
          _emitImmediate((Immediate)(src2), 1);
        return;
      }

      break;
    }

    case I_TEST:
    {
      if (o1.isRegMem() && o2.isReg())
      {
        assert(o1.size() == o2.size());
        _emitX86RM(0x84 + intValue(o2.size() != 1),
          o2.size() == 2, o2.size() == 8,
          ((BaseReg) o2).code(),
          (o1),
          0);
        return;
      }

      if (o1.isRegIndex(0) && o2.isImm())
      {
        int immSize = o1.size() <= 4 ? o1.size() : 4;

        if (o1.size() == 2) _emitByte(0x66); // 16 bit

        if (is64()) {
            _emitRexRM(o1.size() == 8, 0, (o1));
        }

        _emitByte(0xA8 + intValue(o1.size() != 1));
        _emitImmediate((Immediate)(o2), immSize);
        return;
      }

      if (o1.isRegMem() && o2.isImm())
      {
        int immSize = o1.size() <= 4 ? o1.size() : 4;

        if (o1.size() == 2) _emitByte(0x66); // 16 bit
        _emitSegmentPrefix((o1)); // segment prefix

        if (is64()) _emitRexRM(o1.size() == 8, 0, (o1));

        _emitByte(0xF6 + intValue(o1.size() != 1));
        _emitModRM(0, (o1), immSize);
        _emitImmediate((Immediate)(o2), immSize);
        return;
      }

      break;
    }

    case I_XCHG:
    {
      if (o1.isRegMem() && o2.isReg())
      {
        final Operand dst = (o1);
        final Register src = (Register)(o2);

        if (src.isRegType(REG_GPW)) _emitByte(0x66); // 16 bit
        _emitSegmentPrefix(dst); // segment prefix

        if (is64()) _emitRexRM(src.isRegType(REG_GPQ), src.code(), dst);

        // Special opcode for index 0 registers (AX, EAX, RAX vs register)
        if ((dst.op() == OP_REG && dst.size() > 1) &&
            (((Register) dst).code() == 0 ||
             ((Register) src).code() == 0))
        {
          int index = ((Register) dst).code() | src.code();
          _emitByte((byte) (0x90 + index));
          return;
        }

        _emitByte(0x86 + intValue(!src.isRegType(REG_GPB)));
        _emitModRM(src.code(), dst, 0);
        return;
      }

      break;
    }

    case I_MOVBE:
    {
      if (o1.isReg() && o2.isMem())
      {
        _emitX86RM(0x000F38F0,
          o1.isRegType(REG_GPW),
          o1.isRegType(REG_GPQ),
          ((Register) o1).code(),
          (Mem)(o2),
          0);
        return;
      }

      if (o1.isMem() && o2.isReg())
      {
        _emitX86RM(0x000F38F1,
          o2.isRegType(REG_GPW),
          o2.isRegType(REG_GPQ),
          ((Register) o2).code(),
          (Mem)(o1),
          0);
        return;
      }

      break;
    }

    case I_X87_FPU:
    {
      if (o1.isRegType(REG_X87))
      {
        int i1 = ((X87Register) o1).index();
        int i2 = 0;

        if (code != INST_FCOM && code != INST_FCOMP)
        {
          if (!o2.isRegType(REG_X87)) throw new IllegalArgumentException("not x87 reg");
          i2 = ((X87Register) o2).index();
        }
        else if (i1 != 0 && i2 != 0)
        {
          throw new IllegalArgumentException("illegal instruction");
        }

        _emitByte(i1 == 0
          ? ((id.opCode1 & 0xFF000000) >> 24)
          : ((id.opCode1 & 0x00FF0000) >> 16));
        _emitByte(i1 == 0
          ? ((id.opCode1 & 0x0000FF00) >>  8) + i2
          : ((id.opCode1 & 0x000000FF)      ) + i1);
        return;
      }

      if (o1.isMem() && (o1.size() == 4 || o1.size() == 8) && o2.isNone())
      {
        final Mem m = (Mem)(o1);

        // segment prefix
        _emitSegmentPrefix(m);

        _emitByte(o1.size() == 4
          ? ((id.opCode1 & 0xFF000000) >> 24)
          : ((id.opCode1 & 0x00FF0000) >> 16));
        _emitModM(id.opCodeR, m, 0);
        return;
      }

      break;
    }

    case I_X87_STI:
    {
      if (o1.isRegType(REG_X87))
      {
        int i = ((X87Register) o1).index();
        _emitByte(((id.opCode1 & 0x0000FF00) >> 8));
        _emitByte(((id.opCode1 & 0x000000FF) + i));
        return;
      }
      break;
    }

    case I_X87_FSTSW:
    {
      if (o1.isReg() &&
          ((BaseReg) o1).type() <= REG_GPQ &&
          ((BaseReg) o1).index() == 0)
      {
        _emitOpCode(id.opCode2);
        return;
      }

      if (o1.isMem())
      {
        _emitX86RM(id.opCode1, false, 0, id.opCodeR, (Mem)(o1), 0);
        return;
      }

      break;
    }

    case I_X87_MEM_STI:
    {
      if (o1.isRegType(REG_X87))
      {
        _emitByte(((id.opCode2 & 0xFF000000) >> 24));
        _emitByte(((id.opCode2 & 0x00FF0000) >> 16) +
          ((X87Register) o1).index());
        return;
      }

      // ... fall through to I_X87_MEM ...
    }

    case I_X87_MEM:
    {
      if (!o1.isMem()) throw new IllegalArgumentException("not x87 mem");
      final Mem m = (Mem)(o1);

      int opCode = 0x00, mod = 0;

      if (o1.size() == 2 && (id.o1Flags & O_FM_2) != 0)
      {
        opCode = ((id.opCode1 & 0xFF000000) >> 24);
        mod    = id.opCodeR;
      }
      if (o1.size() == 4 && (id.o1Flags & O_FM_4) != 0)
      {
        opCode = ((id.opCode1 & 0x00FF0000) >> 16);
        mod    = id.opCodeR;
      }
      if (o1.size() == 8 && (id.o1Flags & O_FM_8) != 0)
      {
        opCode = ((id.opCode1 & 0x0000FF00) >>  8);
        mod    = ((id.opCode1 & 0x000000FF)      );
      }

      if (opCode != 0)
      {
        _emitSegmentPrefix(m);
        _emitByte(opCode);
        _emitModM(mod, m, 0);
        return;
      }

      break;
    }

    case I_MMU_MOV:
    {
      assert(id.o1Flags != 0);
      assert(id.o2Flags != 0);

      // Check parameters (X)MM|GP32_64 <- (X)MM|GP32_64|Mem|Imm
      if ((o1.isMem()            && (id.o1Flags & O_MEM) == 0) ||
          (o1.isRegType(REG_MM ) && (id.o1Flags & O_MM ) == 0) ||
          (o1.isRegType(REG_XMM) && (id.o1Flags & O_XMM) == 0) ||
          (o1.isRegType(REG_GPD) && (id.o1Flags & O_G32) == 0) ||
          (o1.isRegType(REG_GPQ) && (id.o1Flags & O_G64) == 0) ||
          (o2.isRegType(REG_MM ) && (id.o2Flags & O_MM ) == 0) ||
          (o2.isRegType(REG_XMM) && (id.o2Flags & O_XMM) == 0) ||
          (o2.isRegType(REG_GPD) && (id.o2Flags & O_G32) == 0) ||
          (o2.isRegType(REG_GPQ) && (id.o2Flags & O_G64) == 0) ||
          (o2.isMem()            && (id.o2Flags & O_MEM) == 0) )
      {
        throw new IllegalArgumentException("illegal instruction");
      }

      // Illegal
      if (o1.isMem() && o2.isMem()) throw new IllegalArgumentException("illegal instruction");

      int rexw = ((id.o1Flags|id.o2Flags) & O_NOREX) != 0
        ? 0
        : intValue(o1.isRegType(REG_GPQ) || o1.isRegType(REG_GPQ));

      // (X)MM|Reg <- (X)MM|Reg
      if (o1.isReg() && o2.isReg())
      {
        _emitMmu(id.opCode1, rexw,
          ((BaseReg) o1).code(),
          (BaseReg)(o2),
          0);
        return;
      }

      // (X)MM|Reg <- Mem
      if (o1.isReg() && o2.isMem())
      {
        _emitMmu(id.opCode1, rexw,
          ((BaseReg) o1).code(),
          (Mem)(o2),
          0);
        return;
      }

      // Mem <- (X)MM|Reg
      if (o1.isMem() && o2.isReg())
      {
        _emitMmu(id.opCode2, rexw,
          ((BaseReg) o2).code(),
          (Mem)(o1),
          0);
        return;
      }

      break;
    }

    case I_MMU_MOVD:
    {
      if ((o1.isRegType(REG_MM) || o1.isRegType(REG_XMM)) && (o2.isRegType(REG_GPD) || o2.isMem()))
      {
        _emitMmu(o1.isRegType(REG_XMM) ? 0x66000F6E : 0x00000F6E, 0,
          ((BaseReg) o1).code(),
          (o2),
          0);
        return;
      }

      if ((o1.isRegType(REG_GPD) || o1.isMem()) && (o2.isRegType(REG_MM) || o2.isRegType(REG_XMM)))
      {
        _emitMmu(o2.isRegType(REG_XMM) ? 0x66000F7E : 0x00000F7E, 0,
          ((BaseReg) o2).code(),
          (o1),
          0);
        return;
      }

      break;
    }

    case I_MMU_MOVQ:
    {
      if (o1.isRegType(REG_MM) && o2.isRegType(REG_MM))
      {
        _emitMmu(0x00000F6F, 0,
          ((MMRegister) o1).code(),
          (MMRegister)(o2),
          0);
        return;
      }

      if (o1.isRegType(REG_XMM) && o2.isRegType(REG_XMM))
      {
        _emitMmu(0xF3000F7E, 0,
          ((XMMRegister) o1).code(),
          (XMMRegister)(o2),
          0);
        return;
      }

      // Convenience - movdq2q
      if (o1.isRegType(REG_MM) && o2.isRegType(REG_XMM))
      {
        _emitMmu(0xF2000FD6, 0,
          ((MMRegister) o1).code(),
          (XMMRegister)(o2),
          0);
        return;
      }

      // Convenience - movq2dq
      if (o1.isRegType(REG_XMM) && o2.isRegType(REG_MM))
      {
        _emitMmu(0xF3000FD6, 0,
          ((XMMRegister) o1).code(),
          (MMRegister)(o2),
          0);
        return;
      }

      if (o1.isRegType(REG_MM) && o2.isMem())
      {
        _emitMmu(0x00000F6F, 0,
          ((MMRegister) o1).code(),
          (Mem)(o2),
          0);
        return;
      }

      if (o1.isRegType(REG_XMM) && o2.isMem())
      {
        _emitMmu(0xF3000F7E, 0,
          ((XMMRegister) o1).code(),
          (Mem)(o2),
          0);
        return;
      }

      if (o1.isMem() && o2.isRegType(REG_MM))
      {
        _emitMmu(0x00000F7F, 0,
          ((MMRegister) o2).code(),
          (Mem)(o1),
          0);
        return;
      }

      if (o1.isMem() && o2.isRegType(REG_XMM))
      {
        _emitMmu(0x66000FD6, 0,
          ((XMMRegister) o2).code(),
          (Mem)(o1),
          0);
        return;
      }


        if (is64()) {
          if ((o1.isRegType(REG_MM) || o1.isRegType(REG_XMM)) && (o2.isRegType(REG_GPQ) || o2.isMem()))
          {
            _emitMmu(o1.isRegType(REG_XMM) ? 0x66000F6E : 0x00000F6E, 1,
              ((BaseReg) o1).code(),
              (o2),
              0);
            return;
          }

          if ((o1.isRegType(REG_GPQ) || o1.isMem()) && (o2.isRegType(REG_MM) || o2.isRegType(REG_XMM)))
          {
            _emitMmu(o2.isRegType(REG_XMM) ? 0x66000F7E : 0x00000F7E, 1,
              ((BaseReg) o2).code(),
              (o1),
              0);
            return;
          }
        }

      break;
    }

    case I_MMU_PREFETCH:
    {
      if (o1.isMem() && o2.isImm())
      {
        final Mem mem = (Mem)(o1);
        final Immediate hint = (Immediate)(o2);

        _emitMmu(0x00000F18, 0, (int) hint.value(), mem, 0);
        return;
      }

      break;
    }
View Full Code Here

TOP

Related Classes of jnr.x86asm.HINT

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.