Skip to content

Commit

Permalink
SIB addressing mode for writes.
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeHopcroft committed Nov 11, 2016
1 parent e2789eb commit 6c8ff14
Show file tree
Hide file tree
Showing 5 changed files with 761 additions and 459 deletions.
193 changes: 193 additions & 0 deletions inc/NativeJIT/CodeGen/X64CodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ namespace NativeJIT
};


enum class SIB : uint8_t
{
Scale1 = 0,
Scale2 = 1,
Scale4 = 2,
Scale8 = 3
};


class X64CodeGenerator : public CodeBuffer
{
public:
Expand Down Expand Up @@ -170,6 +179,14 @@ namespace NativeJIT
template <OpCode OP, unsigned SIZE1, bool ISFLOAT1, unsigned SIZE2, bool ISFLOAT2>
void Emit(Register<SIZE1, ISFLOAT1> dest, Register<8, false> src, int32_t srcOffset);

// Scale-index-base (SIB) + offset.
template <OpCode OP, unsigned SIZE, bool ISFLOAT>
void Emit(Register<SIZE, ISFLOAT> dest,
Register<8, false> base,
Register<8, false> index,
SIB scale,
int32_t offset);

// Two operands - indirect destination and register source with the same type and size.
template <OpCode OP, unsigned SIZE, bool ISFLOAT>
void Emit(Register<8, false> dest, int32_t destOffset, Register<SIZE, ISFLOAT> src);
Expand Down Expand Up @@ -323,6 +340,14 @@ namespace NativeJIT
Register<8, false> src,
int32_t srcOffset);

template <unsigned SIZE>
void Group1(uint8_t baseOpCode,
Register<SIZE, false> dest,
Register<8, false> base,
Register<8, false> index,
SIB scale,
int32_t srcOffset);

template <unsigned SIZE>
void Group1(uint8_t baseOpCode,
Register<8, false> dest,
Expand Down Expand Up @@ -438,6 +463,14 @@ namespace NativeJIT
template <unsigned SIZE>
static void Emit(X64CodeGenerator& code, Register<SIZE, ISFLOAT> dest, Register<8, false> src, int32_t srcOffset);

template <unsigned SIZE>
static void Emit(X64CodeGenerator& code,
Register<SIZE, ISFLOAT> dest,
Register<8, false> base,
Register<8, false> index,
SIB scale,
int32_t srcOffset);

template <unsigned SIZE>
static void Emit(X64CodeGenerator& code, Register<8, false> dest, int32_t destOffset, Register<SIZE, ISFLOAT> src);

Expand Down Expand Up @@ -505,6 +538,14 @@ namespace NativeJIT
template <unsigned SIZE1, bool ISFLOAT1, unsigned SIZE2, bool ISFLOAT2>
void Print(OpCode op, Register<SIZE1, ISFLOAT1> dest, Register<8, false> src, int32_t srcOffset);

template <unsigned SIZE1, bool ISFLOAT1>
void Print(OpCode op,
Register<SIZE1, ISFLOAT1> dest,
Register<8u, false> base,
Register<8u, false> index,
SIB scale,
int32_t offset);

template <unsigned SIZE1, bool ISFLOAT1, unsigned SIZE2, bool ISFLOAT2>
void Print(OpCode op, Register<8, false> dest, int32_t destOffset, Register<SIZE2, ISFLOAT2> src);

Expand Down Expand Up @@ -648,6 +689,47 @@ namespace NativeJIT
}


template <unsigned SIZE, bool ISFLOAT>
void X64CodeGenerator::CodePrinter::Print(OpCode op,
Register<SIZE, ISFLOAT> dest,
Register<8u, false> base,
Register<8u, false> index,
SIB scale,
int32_t offset)
{
if (m_out != nullptr)
{
IosMiniStateRestorer state(*m_out);

PrintBytes(m_startPosition, m_code.CurrentPosition());

*m_out << OpCodeName(op)
<< ' ' << dest.GetName()
<< ", "
<< GetPointerName(SIZE)
<< " ptr ["
<< base.GetName()
<< " + "
<< index.GetName()
<< " * "
<< static_cast<unsigned>(scale)
<< std::uppercase
<< std::hex;

if (offset > 0)
{
*m_out << " + " << offset << "h";
}
else if (offset < 0)
{
*m_out << " - " << -static_cast<int64_t>(offset) << "h";
}

*m_out << "]" << std::endl;
}
}


template <unsigned SIZE1, bool ISFLOAT1, unsigned SIZE2, bool ISFLOAT2>
void X64CodeGenerator::CodePrinter::Print(OpCode op,
Register<8, false> dest,
Expand Down Expand Up @@ -843,6 +925,22 @@ namespace NativeJIT
}


// Scale-index-base (SIB) + offset.
template <OpCode OP, unsigned SIZE, bool ISFLOAT>
void X64CodeGenerator::Emit(Register<SIZE, ISFLOAT> dest,
Register<8, false> base,
Register<8, false> index,
SIB scale,
int32_t offset)
{
CodePrinter printer(*this);

Helper<OP>::template ArgTypes1<ISFLOAT>::template Emit<SIZE>(*this, dest, base, index, scale, offset);

printer.Print<SIZE, ISFLOAT>(OP, dest, base, index, scale, offset);
}


template <OpCode OP, unsigned SIZE, bool ISFLOAT>
void X64CodeGenerator::Emit(Register<8, false> dest, int32_t destOffset, Register<SIZE, ISFLOAT> src)
{
Expand Down Expand Up @@ -1372,6 +1470,71 @@ namespace NativeJIT
}


template <unsigned SIZE>
void X64CodeGenerator::Group1(uint8_t baseOpCode,
Register<SIZE, false> dest,
Register<8, false> base,
Register<8, false> index,
SIB scale,
int32_t offset)
{
EmitOpSizeOverrideIndirect<SIZE, false>(dest, base);

//
// Emit rex
//
const bool w = (SIZE == 8);
Emit8(0x40
| (w ? 8 : 0)
| (dest.IsExtended() ? 4 : 0)
| (index.IsExtended() ? 2 : 0)
| (base.IsExtended() ? 1 : 0));

//
// Emit opcode
//

if (SIZE == 1)
{
Emit8(baseOpCode + 0x2);
}
else
{
Emit8(baseOpCode + 0x3);
}

//
// Emit mod/rm
//

uint8_t mod = Mod(offset);
const uint8_t baseField = base.GetId8();
const uint8_t destField = dest.GetId8();
const uint8_t indexField = index.GetId8();

Emit8((mod << 6) | (destField << 3) | 4);

//
// Emit SIB
//
const uint8_t s = static_cast<uint8_t>(scale);
Emit8((s << 6) | (indexField << 3) | baseField);

//
// Emit offset
//

if (mod == 1)
{
Emit8(static_cast<uint8_t>(offset));
}
else if (mod == 2)
{
Emit32(offset);
}
}


template <unsigned SIZE>
void X64CodeGenerator::Group1(uint8_t baseOpCode,
Register<8, false> dest,
Expand Down Expand Up @@ -1796,6 +1959,21 @@ namespace NativeJIT
}


template <>
template <>
template <unsigned SIZE>
void X64CodeGenerator::Helper<OpCode::Mov>::ArgTypes1<false>::Emit(
X64CodeGenerator& code,
Register<SIZE, false> dest,
Register<8, false> base,
Register<8, false> index,
SIB scale,
int32_t srcOffset)
{
code.Group1(0x88, dest, base, index, scale, srcOffset);
}


template <>
template <>
template <unsigned SIZE>
Expand Down Expand Up @@ -2025,6 +2203,21 @@ namespace NativeJIT
template <> \
template <> \
template <unsigned SIZE> \
void X64CodeGenerator::Helper<OpCode::name>::ArgTypes1<false>::Emit( \
X64CodeGenerator& code, \
Register<SIZE, false> dest, \
Register<8, false> base, \
Register<8, false> index, \
SIB scale, \
int32_t srcOffset) \
{ \
code.Group1(baseOpCode, dest, base, index, scale, srcOffset); \
} \
\
\
template <> \
template <> \
template <unsigned SIZE> \
void X64CodeGenerator::Helper<OpCode::name>::ArgTypes1<false>::Emit( \
X64CodeGenerator& code, \
Register<8, false> dest, \
Expand Down
16 changes: 16 additions & 0 deletions src/Assembler/TestAsm.asm
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ movsd xmm0, xmm1
; vmovq xmm0, rax // Illegal instruction
ret

; SIB
mov rax, [rsi + rcx * 8 + 1234h]
mov r15, [r14 + r13 * 8 + 1234h]
mov al, [rcx + r13 * 8 + 12h]
mov bx, [r15 + rax * 8 + 34h]

and rax, [rsi + rcx * 8 + 1234h]
and r15, [r14 + r13 * 8 + 1234h]
and al, [rcx + r13 * 8 + 12h]
and bx, [r15 + rax * 8 + 34h]

and rax, [rdi + rdx * 1 + 5678h]
and rax, [rdi + rdx * 2 + 5678h]
and rax, [rdi + rdx * 4 + 5678h]
and rax, [rdi + rdx * 8 + 5678h]

; Another special case
add r13, [r13]
mov r13, [r13]
Expand Down
Loading

0 comments on commit 6c8ff14

Please sign in to comment.