summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2010-09-07 21:11:23 -0700
committerDavid Schleef <ds@schleef.org>2010-09-07 21:11:23 -0700
commitf28290eedfb0239b68eda369d1a5eba3f9fb76e9 (patch)
tree51caf0cb368075849b783f014d3de437a6797297
parent72f0fcb729762ef808eb16c2706c2e76cca5f6f8 (diff)
sse: Implement ldresnearl
-rw-r--r--orc/orccompiler.c3
-rw-r--r--orc/orcprogram-sse.c76
-rw-r--r--orc/orcprogram.h2
-rw-r--r--orc/orcrules-sse.c138
-rw-r--r--orc/orcsse.c50
-rw-r--r--orc/orcsse.h2
-rw-r--r--orc/orcx86.c69
-rw-r--r--orc/orcx86.h5
8 files changed, 308 insertions, 37 deletions
diff --git a/orc/orccompiler.c b/orc/orccompiler.c
index 512bb46..16b4d76 100644
--- a/orc/orccompiler.c
+++ b/orc/orccompiler.c
@@ -795,6 +795,9 @@ orc_compiler_global_reg_alloc (OrcCompiler *compiler)
var->ptr_offset = orc_compiler_allocate_register (compiler, FALSE);
var->aligned_data = orc_compiler_allocate_register (compiler, TRUE);
}
+ if (var->need_offset_reg) {
+ var->ptr_offset = orc_compiler_allocate_register (compiler, FALSE);
+ }
break;
case ORC_VAR_TYPE_DEST:
var->ptr_register = orc_compiler_allocate_register (compiler, FALSE);
diff --git a/orc/orcprogram-sse.c b/orc/orcprogram-sse.c
index 435630e..89b3bbd 100644
--- a/orc/orcprogram-sse.c
+++ b/orc/orcprogram-sse.c
@@ -254,6 +254,20 @@ orc_compiler_sse_init (OrcCompiler *compiler)
}
compiler->alloc_loop_counter = TRUE;
compiler->allow_gp_on_stack = TRUE;
+
+ {
+ for(i=0;i<compiler->n_insns;i++){
+ OrcInstruction *insn = compiler->insns + i;
+ OrcStaticOpcode *opcode = insn->opcode;
+
+ if (strcmp (opcode->name, "ldreslinb") == 0 ||
+ strcmp (opcode->name, "ldreslinl") == 0 ||
+ strcmp (opcode->name, "ldresnearb") == 0 ||
+ strcmp (opcode->name, "ldresnearl") == 0) {
+ compiler->vars[insn->src_args[0]].need_offset_reg = TRUE;
+ }
+ }
+ }
}
void
@@ -465,6 +479,29 @@ sse_load_constants_outer (OrcCompiler *compiler)
}
}
}
+
+ {
+ for(i=0;i<compiler->n_insns;i++){
+ OrcInstruction *insn = compiler->insns + i;
+ OrcStaticOpcode *opcode = insn->opcode;
+
+ if (strcmp (opcode->name, "ldreslinb") == 0 ||
+ strcmp (opcode->name, "ldreslinl") == 0 ||
+ strcmp (opcode->name, "ldresnearb") == 0 ||
+ strcmp (opcode->name, "ldresnearl") == 0) {
+ if (compiler->vars[insn->src_args[1]].vartype == ORC_VAR_TYPE_PARAM) {
+ orc_x86_emit_mov_memoffset_reg (compiler, 4,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor, params[insn->src_args[1]]),
+ compiler->exec_reg,
+ compiler->vars[insn->src_args[0]].ptr_offset);
+ } else {
+ orc_x86_emit_mov_imm_reg (compiler, 4,
+ compiler->vars[insn->src_args[1]].value.i,
+ compiler->vars[insn->src_args[0]].ptr_offset);
+ }
+ }
+ }
+ }
}
void
@@ -517,6 +554,10 @@ sse_add_strides (OrcCompiler *compiler)
orc_x86_emit_add_reg_memoffset (compiler, compiler->is_64bit ? 8 : 4,
compiler->gp_tmpreg,
(int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[i]), compiler->exec_reg);
+
+ if (compiler->vars[i].ptr_register == 0) {
+ ORC_COMPILER_ERROR(compiler, "unimplemented: stride on mem pointer");
+ }
break;
case ORC_VAR_TYPE_ACCUMULATOR:
break;
@@ -955,18 +996,31 @@ orc_sse_emit_loop (OrcCompiler *compiler, int offset, int update)
if (update) {
for(k=0;k<ORC_N_COMPILER_VARIABLES;k++){
- if (compiler->vars[k].name == NULL) continue;
- if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC ||
- compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) {
- if (compiler->vars[k].ptr_register) {
- orc_x86_emit_add_imm_reg (compiler, compiler->is_64bit ? 8 : 4,
- compiler->vars[k].size * update,
- compiler->vars[k].ptr_register, FALSE);
+ OrcVariable *var = compiler->vars + k;
+
+ if (var->name == NULL) continue;
+ if (var->vartype == ORC_VAR_TYPE_SRC ||
+ var->vartype == ORC_VAR_TYPE_DEST) {
+ int offset;
+ if (var->update_type == 0) {
+ offset = 0;
+ } else if (var->update_type == 1) {
+ offset = (var->size * update) >> 1;
} else {
- orc_x86_emit_add_imm_memoffset (compiler, compiler->is_64bit ? 8 : 4,
- compiler->vars[k].size * update,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]),
- compiler->exec_reg);
+ offset = var->size * update;
+ }
+
+ if (offset != 0) {
+ if (compiler->vars[k].ptr_register) {
+ orc_x86_emit_add_imm_reg (compiler, compiler->is_64bit ? 8 : 4,
+ offset,
+ compiler->vars[k].ptr_register, FALSE);
+ } else {
+ orc_x86_emit_add_imm_memoffset (compiler, compiler->is_64bit ? 8 : 4,
+ offset,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[k]),
+ compiler->exec_reg);
+ }
}
}
}
diff --git a/orc/orcprogram.h b/orc/orcprogram.h
index 634ea27..e46a53f 100644
--- a/orc/orcprogram.h
+++ b/orc/orcprogram.h
@@ -231,6 +231,8 @@ struct _OrcVariable {
int aligned_data;
int param_type;
int load_dest;
+ int update_type;
+ int need_offset_reg;
};
/**
diff --git a/orc/orcrules-sse.c b/orc/orcrules-sse.c
index b9a3b9f..2b69b2d 100644
--- a/orc/orcrules-sse.c
+++ b/orc/orcrules-sse.c
@@ -97,6 +97,8 @@ sse_rule_loadX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
src->size << compiler->loop_shift);
break;
}
+
+ src->update_type = 2;
}
static void
@@ -150,6 +152,8 @@ sse_rule_loadoffX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
src->size << compiler->loop_shift);
break;
}
+
+ src->update_type = 2;
}
static void
@@ -161,7 +165,7 @@ sse_rule_loadupib (OrcCompiler *compiler, void *user, OrcInstruction *insn)
int offset = 0;
int tmp = orc_compiler_get_temp_reg (compiler);
- offset = compiler->offset * src->size;
+ offset = (compiler->offset * src->size) >> 1;
if (src->ptr_register == 0) {
int i = insn->src_args[0];
orc_x86_emit_mov_memoffset_reg (compiler, compiler->is_64bit ? 8 : 4,
@@ -209,17 +213,7 @@ sse_rule_loadupib (OrcCompiler *compiler, void *user, OrcInstruction *insn)
orc_sse_emit_pavgb (compiler, dest->alloc, tmp);
orc_sse_emit_punpcklbw (compiler, tmp, dest->alloc);
- /* FIXME hack */
- if (src->ptr_register) {
- orc_x86_emit_add_imm_reg (compiler, compiler->is_64bit ? 8 : 4,
- -(src->size << compiler->loop_shift)>>1,
- src->ptr_register, FALSE);
- } else {
- orc_x86_emit_add_imm_memoffset (compiler, compiler->is_64bit ? 8 : 4,
- -(src->size << compiler->loop_shift)>>1,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[insn->src_args[0]]),
- compiler->exec_reg);
- }
+ src->update_type = 1;
}
static void
@@ -230,7 +224,7 @@ sse_rule_loadupdb (OrcCompiler *compiler, void *user, OrcInstruction *insn)
int ptr_reg;
int offset = 0;
- offset = compiler->offset * src->size;
+ offset = (compiler->offset * src->size) >> 1;
if (src->ptr_register == 0) {
int i = insn->src_args[0];
orc_x86_emit_mov_memoffset_reg (compiler, compiler->is_64bit ? 8 : 4,
@@ -278,17 +272,8 @@ sse_rule_loadupdb (OrcCompiler *compiler, void *user, OrcInstruction *insn)
orc_sse_emit_punpckldq (compiler, dest->alloc, dest->alloc);
break;
}
- /* FIXME hack */
- if (src->ptr_register) {
- orc_x86_emit_add_imm_reg (compiler, compiler->is_64bit ? 8 : 4,
- -(src->size << compiler->loop_shift)>>1,
- src->ptr_register, FALSE);
- } else {
- orc_x86_emit_add_imm_memoffset (compiler, compiler->is_64bit ? 8 : 4,
- -(src->size << compiler->loop_shift)>>1,
- (int)ORC_STRUCT_OFFSET(OrcExecutor, arrays[insn->src_args[0]]),
- compiler->exec_reg);
- }
+
+ src->update_type = 1;
}
static void
@@ -347,6 +332,110 @@ sse_rule_storeX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
ORC_COMPILER_ERROR(compiler,"bad size");
break;
}
+
+ dest->update_type = 2;
+}
+
+#if try1
+static void
+sse_rule_ldresnearl (OrcCompiler *compiler, void *user, OrcInstruction *insn)
+{
+ OrcVariable *src = compiler->vars + insn->src_args[0];
+ OrcVariable *dest = compiler->vars + insn->dest_args[0];
+ int tmp = orc_compiler_get_temp_reg (compiler);
+ int tmp2 = orc_compiler_get_temp_reg (compiler);
+ int tmpc;
+
+ orc_x86_emit_mov_sse_reg (compiler, X86_XMM6, compiler->gp_tmpreg);
+ orc_x86_emit_sar_imm_reg (compiler, 4, 16, compiler->gp_tmpreg);
+
+ ORC_ASM_CODE(compiler," movdqu 0(%%%s,%%%s,4), %%%s\n",
+ orc_x86_get_regname_ptr(compiler, src->ptr_register),
+ orc_x86_get_regname_ptr(compiler, compiler->gp_tmpreg),
+ orc_x86_get_regname_sse(dest->alloc));
+ *compiler->codeptr++ = 0xf3;
+ orc_x86_emit_rex(compiler, 0, dest->ptr_register, 0, dest->alloc);
+ *compiler->codeptr++ = 0x0f;
+ *compiler->codeptr++ = 0x6f;
+ orc_x86_emit_modrm_memindex (compiler, dest->alloc, 0,
+ src->ptr_register, compiler->gp_tmpreg, 2);
+
+#if 0
+ orc_sse_emit_movdqa (compiler, X86_XMM6, tmp);
+ orc_sse_emit_pslld (compiler, 10, tmp);
+ orc_sse_emit_psrld (compiler, 26, tmp);
+ orc_sse_emit_pslld (compiler, 2, tmp);
+
+ orc_sse_emit_movdqa (compiler, tmp, tmp2);
+ orc_sse_emit_pslld (compiler, 8, tmp2);
+ orc_sse_emit_por (compiler, tmp2, tmp);
+ orc_sse_emit_movdqa (compiler, tmp, tmp2);
+ orc_sse_emit_pslld (compiler, 16, tmp2);
+ orc_sse_emit_por (compiler, tmp2, tmp);
+#else
+ orc_sse_emit_movdqa (compiler, X86_XMM6, tmp);
+ tmpc = orc_compiler_get_constant_long (compiler, 0x02020202,
+ 0x06060606, 0x0a0a0a0a, 0x0e0e0e0e);
+ orc_sse_emit_pshufb (compiler, tmpc, tmp);
+ orc_sse_emit_paddb (compiler, tmp, tmp);
+ orc_sse_emit_paddb (compiler, tmp, tmp);
+#endif
+
+ orc_sse_emit_pshufd (compiler, ORC_SSE_SHUF(0,0,0,0), tmp, tmp2);
+ orc_sse_emit_psubd (compiler, tmp2, tmp);
+ tmpc = orc_compiler_get_constant (compiler, 4, 0x03020100);
+ orc_sse_emit_paddd (compiler, tmpc, tmp);
+
+ orc_sse_emit_pshufb (compiler, tmp, dest->alloc);
+
+ orc_sse_emit_movdqa (compiler, X86_XMM7, tmp);
+ orc_sse_emit_pslld (compiler, compiler->loop_shift, tmp);
+
+ orc_sse_emit_paddd (compiler, tmp, X86_XMM6);
+
+ src->update_type = 0;
+}
+#endif
+
+static void
+sse_rule_ldresnearl (OrcCompiler *compiler, void *user, OrcInstruction *insn)
+{
+ OrcVariable *src = compiler->vars + insn->src_args[0];
+ int increment_var = insn->src_args[2];
+ OrcVariable *dest = compiler->vars + insn->dest_args[0];
+ int tmp = orc_compiler_get_temp_reg (compiler);
+ int i;
+
+ for(i=0;i<(1<<compiler->loop_shift);i++){
+ if (i == 0) {
+ orc_x86_emit_mov_memoffset_sse (compiler, 4, 0,
+ src->ptr_register, dest->alloc, FALSE);
+ } else {
+ orc_x86_emit_mov_memindex_sse (compiler, 4, 0,
+ src->ptr_register, compiler->gp_tmpreg, 2, tmp, FALSE);
+ orc_sse_emit_pslldq (compiler, 4*i, tmp);
+ orc_sse_emit_por (compiler, tmp, dest->alloc);
+ }
+
+ if (compiler->vars[increment_var].vartype == ORC_VAR_TYPE_PARAM) {
+ orc_x86_emit_add_memoffset_reg (compiler, 4,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor, params[increment_var]),
+ compiler->exec_reg, src->ptr_offset);
+ } else {
+ orc_x86_emit_add_imm_reg (compiler, 4,
+ compiler->vars[increment_var].value.i,
+ src->ptr_offset, FALSE);
+ }
+
+ orc_x86_emit_mov_reg_reg (compiler, 4, src->ptr_offset, compiler->gp_tmpreg);
+ orc_x86_emit_sar_imm_reg (compiler, 4, 16, compiler->gp_tmpreg);
+ }
+
+ orc_x86_emit_add_reg_reg_shift (compiler, 4, compiler->gp_tmpreg,
+ src->ptr_register, 2);
+ orc_x86_emit_and_imm_reg (compiler, 4, 0xffff, src->ptr_offset);
+
+ src->update_type = 0;
}
static void
@@ -2194,6 +2283,7 @@ orc_compiler_sse_register_rules (OrcTarget *target)
orc_rule_register (rule_set, "loadpw", sse_rule_loadpX, (void *)2);
orc_rule_register (rule_set, "loadpl", sse_rule_loadpX, (void *)4);
orc_rule_register (rule_set, "loadpq", sse_rule_loadpX, (void *)8);
+ orc_rule_register (rule_set, "ldresnearl", sse_rule_ldresnearl, NULL);
orc_rule_register (rule_set, "storeb", sse_rule_storeX, NULL);
orc_rule_register (rule_set, "storew", sse_rule_storeX, NULL);
diff --git a/orc/orcsse.c b/orc/orcsse.c
index 725e04b..f812075 100644
--- a/orc/orcsse.c
+++ b/orc/orcsse.c
@@ -244,6 +244,56 @@ orc_x86_emit_mov_memoffset_sse (OrcCompiler *compiler, int size, int offset,
}
void
+orc_x86_emit_mov_memindex_sse (OrcCompiler *compiler, int size, int offset,
+ int reg1, int regindex, int shift, int reg2, int is_aligned)
+{
+ switch (size) {
+ case 4:
+ ORC_ASM_CODE(compiler," movd %d(%%%s,%%%s,%d), %%%s\n", offset,
+ orc_x86_get_regname_ptr(compiler, reg1),
+ orc_x86_get_regname_ptr(compiler, regindex), 1<<shift,
+ orc_x86_get_regname_sse(reg2));
+ *compiler->codeptr++ = 0x66;
+ orc_x86_emit_rex(compiler, 0, reg2, 0, reg1);
+ *compiler->codeptr++ = 0x0f;
+ *compiler->codeptr++ = 0x6e;
+ break;
+ case 8:
+ ORC_ASM_CODE(compiler," movq %d(%%%s,%%%s,%d), %%%s\n", offset, orc_x86_get_regname_ptr(compiler, reg1),
+ orc_x86_get_regname_ptr(compiler, regindex), 1<<shift,
+ orc_x86_get_regname_sse(reg2));
+ *compiler->codeptr++ = 0xf3;
+ orc_x86_emit_rex(compiler, 0, reg2, 0, reg1);
+ *compiler->codeptr++ = 0x0f;
+ *compiler->codeptr++ = 0x7e;
+ break;
+ case 16:
+ if (is_aligned) {
+ ORC_ASM_CODE(compiler," movdqa %d(%%%s,%%%s,%d), %%%s\n", offset, orc_x86_get_regname_ptr(compiler, reg1),
+ orc_x86_get_regname_ptr(compiler, regindex), 1<<shift,
+ orc_x86_get_regname_sse(reg2));
+ *compiler->codeptr++ = 0x66;
+ orc_x86_emit_rex(compiler, 0, reg2, 0, reg1);
+ *compiler->codeptr++ = 0x0f;
+ *compiler->codeptr++ = 0x6f;
+ } else {
+ ORC_ASM_CODE(compiler," movdqu %d(%%%s,%%%s,%d), %%%s\n", offset, orc_x86_get_regname_ptr(compiler, reg1),
+ orc_x86_get_regname_ptr(compiler, regindex), 1<<shift,
+ orc_x86_get_regname_sse(reg2));
+ *compiler->codeptr++ = 0xf3;
+ orc_x86_emit_rex(compiler, 0, reg2, 0, reg1);
+ *compiler->codeptr++ = 0x0f;
+ *compiler->codeptr++ = 0x6f;
+ }
+ break;
+ default:
+ ORC_COMPILER_ERROR(compiler, "bad size");
+ break;
+ }
+ orc_x86_emit_modrm_memindex (compiler, reg2, offset, reg1, regindex, shift);
+}
+
+void
orc_x86_emit_mov_sse_memoffset (OrcCompiler *compiler, int size, int reg1, int offset,
int reg2, int aligned, int uncached)
{
diff --git a/orc/orcsse.h b/orc/orcsse.h
index 32a4593..e662824 100644
--- a/orc/orcsse.h
+++ b/orc/orcsse.h
@@ -41,6 +41,8 @@ typedef enum {
const char * orc_x86_get_regname_sse(int i);
void orc_x86_emit_mov_memoffset_sse (OrcCompiler *compiler, int size, int offset,
int reg1, int reg2, int is_aligned);
+void orc_x86_emit_mov_memindex_sse (OrcCompiler *compiler, int size, int offset,
+ int reg1, int regindex, int shift, int reg2, int is_aligned);
void orc_x86_emit_mov_sse_memoffset (OrcCompiler *compiler, int size, int reg1, int offset,
int reg2, int aligned, int uncached);
void orc_x86_emit_mov_sse_reg_reg (OrcCompiler *compiler, int reg1, int reg2);
diff --git a/orc/orcx86.c b/orc/orcx86.c
index 85a63b1..c857eb7 100644
--- a/orc/orcx86.c
+++ b/orc/orcx86.c
@@ -168,6 +168,26 @@ orc_x86_emit_modrm_memoffset (OrcCompiler *compiler, int reg1, int offset, int r
}
}
+void orc_x86_emit_modrm_memindex (OrcCompiler *compiler, int reg1, int offset,
+ int reg2, int regindex, int shift)
+{
+ if (offset == 0) {
+ *compiler->codeptr++ = X86_MODRM(0, 4, reg1);
+ *compiler->codeptr++ = X86_SIB(shift, regindex, reg2);
+ } else if (offset >= -128 && offset < 128) {
+ *compiler->codeptr++ = X86_MODRM(1, 4, reg1);
+ *compiler->codeptr++ = X86_SIB(shift, regindex, reg2);
+ *compiler->codeptr++ = (offset & 0xff);
+ } else {
+ *compiler->codeptr++ = X86_MODRM(2, 4, reg1);
+ *compiler->codeptr++ = X86_SIB(shift, regindex, reg2);
+ *compiler->codeptr++ = (offset & 0xff);
+ *compiler->codeptr++ = ((offset>>8) & 0xff);
+ *compiler->codeptr++ = ((offset>>16) & 0xff);
+ *compiler->codeptr++ = ((offset>>24) & 0xff);
+ }
+}
+
void
orc_x86_emit_modrm_reg (OrcCompiler *compiler, int reg1, int reg2)
{
@@ -475,7 +495,7 @@ orc_x86_emit_add_imm_reg (OrcCompiler *compiler, int size, int value, int reg, o
{
if (!record) {
if (size == 4 && !compiler->is_64bit) {
- ORC_ASM_CODE(compiler," lea %d(%%%s), %%%s\n", value,
+ ORC_ASM_CODE(compiler," leal %d(%%%s), %%%s\n", value,
orc_x86_get_regname(reg), orc_x86_get_regname(reg));
orc_x86_emit_rex(compiler, size, 0, 0, reg);
*compiler->codeptr++ = 0x8d;
@@ -483,7 +503,7 @@ orc_x86_emit_add_imm_reg (OrcCompiler *compiler, int size, int value, int reg, o
return;
}
if (size == 8 && compiler->is_64bit) {
- ORC_ASM_CODE(compiler," lea %d(%%%s), %%%s\n", value,
+ ORC_ASM_CODE(compiler," leaq %d(%%%s), %%%s\n", value,
orc_x86_get_regname_64(reg), orc_x86_get_regname_64(reg));
orc_x86_emit_rex(compiler, size, reg, 0, reg);
*compiler->codeptr++ = 0x8d;
@@ -519,6 +539,27 @@ orc_x86_emit_add_imm_reg (OrcCompiler *compiler, int size, int value, int reg, o
}
void
+orc_x86_emit_add_reg_reg_shift (OrcCompiler *compiler, int size, int reg1,
+ int reg2, int shift)
+{
+ if (size == 4) {
+ ORC_ASM_CODE(compiler," leal (%%%s, %%%s, %d), %%%s\n",
+ orc_x86_get_regname(reg2),
+ orc_x86_get_regname(reg1), 1<<shift,
+ orc_x86_get_regname(reg2));
+ } else {
+ ORC_ASM_CODE(compiler," leaq (%%%s, %%%s, %d), %%%s\n",
+ orc_x86_get_regname(reg2),
+ orc_x86_get_regname(reg1), 1<<shift,
+ orc_x86_get_regname(reg2));
+ }
+
+ orc_x86_emit_rex(compiler, size, reg2, 0, reg1);
+ *compiler->codeptr++ = 0x8d;
+ orc_x86_emit_modrm_memindex (compiler, reg2, 0, reg2, reg1, shift);
+}
+
+void
orc_x86_emit_add_reg_reg (OrcCompiler *compiler, int size, int reg1, int reg2)
{
if (size == 2) {
@@ -573,6 +614,30 @@ orc_x86_emit_imul_memoffset_reg (OrcCompiler *compiler, int size,
}
void
+orc_x86_emit_add_memoffset_reg (OrcCompiler *compiler, int size,
+ int offset, int reg, int destreg)
+{
+ if (size == 2) {
+ ORC_ASM_CODE(compiler," addw %d(%%%s), %%%s\n", offset,
+ orc_x86_get_regname_ptr(compiler, reg),
+ orc_x86_get_regname_16(destreg));
+ *compiler->codeptr++ = 0x66;
+ } else if (size == 4) {
+ ORC_ASM_CODE(compiler," addl %d(%%%s), %%%s\n", offset,
+ orc_x86_get_regname_ptr(compiler, reg),
+ orc_x86_get_regname(destreg));
+ } else {
+ ORC_ASM_CODE(compiler," add %d(%%%s), %%%s\n", offset,
+ orc_x86_get_regname_ptr(compiler, reg),
+ orc_x86_get_regname_64(destreg));
+ }
+
+ orc_x86_emit_rex(compiler, size, 0, 0, reg);
+ *compiler->codeptr++ = 0x03;
+ orc_x86_emit_modrm_memoffset (compiler, destreg, offset, reg);
+}
+
+void
orc_x86_emit_sub_memoffset_reg (OrcCompiler *compiler, int size,
int offset, int reg, int destreg)
{
diff --git a/orc/orcx86.h b/orc/orcx86.h
index 3e3b48c..05b4f9f 100644
--- a/orc/orcx86.h
+++ b/orc/orcx86.h
@@ -61,10 +61,13 @@ void orc_x86_emit_and_imm_memoffset (OrcCompiler *compiler, int size, int value,
void orc_x86_emit_add_imm_reg (OrcCompiler *compiler, int size, int value, int reg, orc_bool record);
void orc_x86_emit_and_imm_reg (OrcCompiler *compiler, int size, int value, int reg);
void orc_x86_emit_or_imm_reg (OrcCompiler *compiler, int size, int value, int reg);
+void orc_x86_emit_add_reg_reg_shift (OrcCompiler *compiler, int size, int reg1, int reg2, int shift);
void orc_x86_emit_add_reg_reg (OrcCompiler *compiler, int size, int reg1, int reg2);
void orc_x86_emit_sub_reg_reg (OrcCompiler *compiler, int size, int reg1, int reg2);
void orc_x86_emit_imul_memoffset_reg (OrcCompiler *compiler, int size,
int offset, int reg, int destreg);
+void orc_x86_emit_add_memoffset_reg (OrcCompiler *compiler, int size,
+ int offset, int reg, int destreg);
void orc_x86_emit_sub_memoffset_reg (OrcCompiler *compiler, int size,
int offset, int reg, int destreg);
void orc_x86_emit_cmp_reg_memoffset (OrcCompiler *compiler, int size, int reg1,
@@ -91,6 +94,8 @@ void orc_x86_emit_epilogue (OrcCompiler *compiler);
void orc_x86_emit_rex (OrcCompiler *compiler, int size, int reg1, int reg2, int reg3);
void orc_x86_emit_modrm_memoffset (OrcCompiler *compiler, int reg1, int offset, int reg2);
void orc_x86_emit_modrm_reg (OrcCompiler *compiler, int reg1, int reg2);
+void orc_x86_emit_modrm_memindex (OrcCompiler *compiler, int reg1, int offset,
+ int reg2, int regindex, int shift);
void orc_x86_do_fixups (OrcCompiler *compiler);