summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2010-09-07 21:09:51 -0700
committerDavid Schleef <ds@schleef.org>2010-09-07 21:09:51 -0700
commit72f0fcb729762ef808eb16c2706c2e76cca5f6f8 (patch)
tree8b2da14ddb77ee00c44c9cdb8103af142beb3863
parentab8f4f5174cb4a55d21744639d3e63dbbc8856d7 (diff)
compiler: Implement long (128-bit) constants
-rw-r--r--orc/orccompiler.c48
-rw-r--r--orc/orcprogram-sse.c38
-rw-r--r--orc/orcprogram.h7
3 files changed, 88 insertions, 5 deletions
diff --git a/orc/orccompiler.c b/orc/orccompiler.c
index acfda58..512bb46 100644
--- a/orc/orccompiler.c
+++ b/orc/orccompiler.c
@@ -984,6 +984,13 @@ orc_compiler_load_constant (OrcCompiler *compiler, int reg, int size,
compiler->target->load_constant (compiler, reg, size, value);
}
+void
+orc_compiler_load_constant_long (OrcCompiler *compiler, int reg,
+ OrcConstant *constant)
+{
+ compiler->target->load_constant_long (compiler, reg, constant);
+}
+
int
orc_compiler_get_temp_constant (OrcCompiler *compiler, int size, int value)
{
@@ -1010,7 +1017,8 @@ orc_compiler_get_constant (OrcCompiler *compiler, int size, int value)
}
for(i=0;i<compiler->n_constants;i++){
- if (compiler->constants[i].value == value) {
+ if (compiler->constants[i].is_long == FALSE &&
+ compiler->constants[i].value == value) {
break;
}
}
@@ -1019,6 +1027,7 @@ orc_compiler_get_constant (OrcCompiler *compiler, int size, int value)
compiler->constants[i].value = value;
compiler->constants[i].alloc_reg = 0;
compiler->constants[i].use_count = 0;
+ compiler->constants[i].is_long = FALSE;
}
compiler->constants[i].use_count++;
@@ -1032,6 +1041,43 @@ orc_compiler_get_constant (OrcCompiler *compiler, int size, int value)
}
int
+orc_compiler_get_constant_long (OrcCompiler *compiler,
+ orc_uint32 a, orc_uint32 b, orc_uint32 c, orc_uint32 d)
+{
+ int i;
+ int tmp;
+
+ for(i=0;i<compiler->n_constants;i++){
+ if (compiler->constants[i].is_long == TRUE &&
+ compiler->constants[i].full_value[0] == a &&
+ compiler->constants[i].full_value[1] == b &&
+ compiler->constants[i].full_value[2] == c &&
+ compiler->constants[i].full_value[3] == d) {
+ break;
+ }
+ }
+ if (i == compiler->n_constants) {
+ compiler->n_constants++;
+ compiler->constants[i].full_value[0] = a;
+ compiler->constants[i].full_value[1] = b;
+ compiler->constants[i].full_value[2] = c;
+ compiler->constants[i].full_value[3] = d;
+ compiler->constants[i].is_long = TRUE;
+ compiler->constants[i].alloc_reg = 0;
+ compiler->constants[i].use_count = 0;
+ }
+
+ compiler->constants[i].use_count++;
+
+ if (compiler->constants[i].alloc_reg != 0) {;
+ return compiler->constants[i].alloc_reg;
+ }
+ tmp = orc_compiler_get_temp_reg (compiler);
+ orc_compiler_load_constant_long (compiler, tmp, &compiler->constants[i]);
+ return tmp;
+}
+
+int
orc_compiler_get_constant_reg (OrcCompiler *compiler)
{
int j;
diff --git a/orc/orcprogram-sse.c b/orc/orcprogram-sse.c
index e1a1153..435630e 100644
--- a/orc/orcprogram-sse.c
+++ b/orc/orcprogram-sse.c
@@ -30,6 +30,8 @@ void orc_sse_emit_invariants (OrcCompiler *compiler);
void orc_compiler_rewrite_vars (OrcCompiler *compiler);
void orc_compiler_dump (OrcCompiler *compiler);
void sse_load_constant (OrcCompiler *compiler, int reg, int size, int value);
+void sse_load_constant_long (OrcCompiler *compiler, int reg,
+ OrcConstant *constant);
static const char * sse_get_flag_name (int shift);
static OrcTarget sse_target = {
@@ -48,7 +50,8 @@ static OrcTarget sse_target = {
NULL,
sse_load_constant,
sse_get_flag_name,
- NULL
+ NULL,
+ sse_load_constant_long
};
@@ -394,6 +397,30 @@ sse_load_constant (OrcCompiler *compiler, int reg, int size, int value)
}
void
+sse_load_constant_long (OrcCompiler *compiler, int reg,
+ OrcConstant *constant)
+{
+ int i;
+ int offset = ORC_STRUCT_OFFSET(OrcExecutor,arrays[ORC_VAR_T1]);
+
+ /* FIXME this is slower than it could be */
+
+ ORC_ASM_CODE(compiler, "# loading constant %08x %08x %08x %08x\n",
+ constant->full_value[0], constant->full_value[1],
+ constant->full_value[2], constant->full_value[3]);
+
+ for(i=0;i<4;i++){
+ orc_x86_emit_mov_imm_reg (compiler, 4, constant->full_value[i],
+ compiler->gp_tmpreg);
+ orc_x86_emit_mov_reg_memoffset (compiler, 4, compiler->gp_tmpreg,
+ offset + 4*i, compiler->exec_reg);
+ }
+ orc_x86_emit_mov_memoffset_sse (compiler, 16, offset, compiler->exec_reg,
+ reg, FALSE);
+
+}
+
+void
sse_load_constants_outer (OrcCompiler *compiler)
{
int i;
@@ -429,8 +456,13 @@ sse_load_constants_outer (OrcCompiler *compiler)
for(i=0;i<compiler->n_constants;i++){
if (compiler->constants[i].alloc_reg) {
- sse_load_constant (compiler, compiler->constants[i].alloc_reg,
- 4, compiler->constants[i].value);
+ if (compiler->constants[i].is_long) {
+ sse_load_constant_long (compiler, compiler->constants[i].alloc_reg,
+ compiler->constants + i);
+ } else {
+ sse_load_constant (compiler, compiler->constants[i].alloc_reg,
+ 4, compiler->constants[i].value);
+ }
}
}
}
diff --git a/orc/orcprogram.h b/orc/orcprogram.h
index 1185667..634ea27 100644
--- a/orc/orcprogram.h
+++ b/orc/orcprogram.h
@@ -325,6 +325,7 @@ struct _OrcConstant {
unsigned int value;
unsigned int full_value[4];
int use_count;
+ int is_long;
};
/**
@@ -603,8 +604,10 @@ struct _OrcTarget {
void (*load_constant)(OrcCompiler *compiler, int reg, int size, int value);
const char * (*get_flag_name)(int shift);
void (*flush_cache) (OrcCode *code);
+ void (*load_constant_long)(OrcCompiler *compiler, int reg,
+ OrcConstant *constant);
- void *_unused[6];
+ void *_unused[5];
};
@@ -714,6 +717,8 @@ int orc_program_allocate_register (OrcProgram *program, int is_data);
void orc_code_allocate_codemem (OrcCode *code, int size);
int orc_compiler_label_new (OrcCompiler *compiler);
int orc_compiler_get_constant (OrcCompiler *compiler, int size, int value);
+int orc_compiler_get_constant_long (OrcCompiler *compiler, orc_uint32 a,
+ orc_uint32 b, orc_uint32 c, orc_uint32 d);
int orc_compiler_get_temp_constant (OrcCompiler *compiler, int size, int value);
int orc_compiler_get_temp_reg (OrcCompiler *compiler);
int orc_compiler_get_constant_reg (OrcCompiler *compiler);