summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--orc/orcarm.c94
-rw-r--r--orc/orcarm.h4
-rw-r--r--orc/orcprogram-arm.c6
-rw-r--r--orc/orcprogram-neon.c26
4 files changed, 98 insertions, 32 deletions
diff --git a/orc/orcarm.c b/orc/orcarm.c
index e89066e..065fab4 100644
--- a/orc/orcarm.c
+++ b/orc/orcarm.c
@@ -79,45 +79,91 @@ orc_arm_emit_bx_lr (OrcCompiler *compiler)
}
void
-orc_arm_emit_push (OrcCompiler *compiler, int regs)
+orc_arm_emit_push (OrcCompiler *compiler, int regs, orc_uint32 vregs)
{
int i;
- int x = 0;
-
- ORC_ASM_CODE(compiler," push {");
- for(i=0;i<16;i++){
- if (regs & (1<<i)) {
- x |= (1<<i);
- ORC_ASM_CODE(compiler,"r%d", i);
- if (x != regs) {
- ORC_ASM_CODE(compiler,", ");
+
+ if (regs) {
+ int x = 0;
+
+ ORC_ASM_CODE(compiler," push {");
+ for(i=0;i<16;i++){
+ if (regs & (1<<i)) {
+ x |= (1<<i);
+ ORC_ASM_CODE(compiler,"r%d", i);
+ if (x != regs) {
+ ORC_ASM_CODE(compiler,", ");
+ }
}
}
+ ORC_ASM_CODE(compiler,"}\n");
+
+ orc_arm_emit (compiler, 0xe92d0000 | regs);
}
- ORC_ASM_CODE(compiler,"}\n");
- orc_arm_emit (compiler, 0xe92d0000 | regs);
+ if (vregs) {
+ int first = -1, last = -1, nregs;
+
+ ORC_ASM_CODE(compiler, " vpush {");
+ for(i=0; i<32; ++i) {
+ if (vregs & (1U << i)) {
+ if (first==-1) {
+ ORC_ASM_CODE(compiler, "d%d", i);
+ first = i;
+ }
+ last = i;
+ }
+ }
+ // What's the deal with even/odd registers ?
+ ORC_ASM_CODE(compiler, "-d%d}\n", last+1);
+
+ nregs = last + 1 - first + 1;
+ orc_arm_emit (compiler, 0xed2d0b00 | ((first & 0x10) << 22) | ((first & 0x0f) << 12) | (nregs << 1));
+ }
}
void
-orc_arm_emit_pop (OrcCompiler *compiler, int regs)
+orc_arm_emit_pop (OrcCompiler *compiler, int regs, orc_uint32 vregs)
{
int i;
- int x = 0;
-
- ORC_ASM_CODE(compiler," pop {");
- for(i=0;i<16;i++){
- if (regs & (1<<i)) {
- x |= (1<<i);
- ORC_ASM_CODE(compiler,"r%d", i);
- if (x != regs) {
- ORC_ASM_CODE(compiler,", ");
+
+
+ if (vregs) {
+ int first = -1, last = -1, nregs;
+
+ ORC_ASM_CODE(compiler, " vpop {");
+ for(i=0; i<32; ++i) {
+ if (vregs & (1U << i)) {
+ if (first==-1) {
+ ORC_ASM_CODE(compiler, "d%d", i);
+ first = i;
+ }
+ last = i;
}
}
+ ORC_ASM_CODE(compiler, "-d%d}\n", last+1);
+
+ nregs = last + 1 - first + 1;
+ orc_arm_emit (compiler, 0xecbd0b00 | ((first & 0x10) << 22) | ((first & 0x0f) << 12) | (nregs << 1));
}
- ORC_ASM_CODE(compiler,"}\n");
- orc_arm_emit (compiler, 0xe8bd0000 | regs);
+ if (regs) {
+ int x = 0;
+
+ ORC_ASM_CODE(compiler," pop {");
+ for(i=0;i<16;i++){
+ if (regs & (1<<i)) {
+ x |= (1<<i);
+ ORC_ASM_CODE(compiler,"r%d", i);
+ if (x != regs) {
+ ORC_ASM_CODE(compiler,", ");
+ }
+ }
+ }
+ ORC_ASM_CODE(compiler,"}\n");
+
+ orc_arm_emit (compiler, 0xe8bd0000 | regs);
+ }
}
void
diff --git a/orc/orcarm.h b/orc/orcarm.h
index 75651c1..1187aa3 100644
--- a/orc/orcarm.h
+++ b/orc/orcarm.h
@@ -92,8 +92,8 @@ void orc_arm_emit_mov (OrcCompiler *compiler, int dest, int src);
void orc_arm_emit_align (OrcCompiler *compiler, int align_shift);
void orc_arm_emit_label (OrcCompiler *compiler, int label);
-void orc_arm_emit_push (OrcCompiler *compiler, int regs);
-void orc_arm_emit_pop (OrcCompiler *compiler, int regs);
+void orc_arm_emit_push (OrcCompiler *compiler, int regs, orc_uint32 vregs);
+void orc_arm_emit_pop (OrcCompiler *compiler, int regs, orc_uint32 vregs);
void orc_arm_emit_branch (OrcCompiler *compiler, int cond, int label);
void orc_arm_emit_data (OrcCompiler *compiler, orc_uint32 data);
diff --git a/orc/orcprogram-arm.c b/orc/orcprogram-arm.c
index 1b62f78..86b7cf6 100644
--- a/orc/orcprogram-arm.c
+++ b/orc/orcprogram-arm.c
@@ -41,7 +41,7 @@ orc_arm_emit_prologue (OrcCompiler *compiler)
regs |= (1<<i);
}
}
- if (regs) orc_arm_emit_push (compiler, regs);
+ if (regs) orc_arm_emit_push (compiler, regs, 0U);
}
@@ -52,7 +52,7 @@ orc_arm_dump_insns (OrcCompiler *compiler)
orc_arm_emit_add_r (compiler, ORC_ARM_COND_AL, 0, ORC_ARM_A2, ORC_ARM_A3, ORC_ARM_A4);
orc_arm_emit_sub_r (compiler, ORC_ARM_COND_AL, 0, ORC_ARM_A2, ORC_ARM_A3, ORC_ARM_A4);
- orc_arm_emit_push (compiler, 0x06);
+ orc_arm_emit_push (compiler, 0x06, 0U);
orc_arm_emit_mov_r (compiler, ORC_ARM_COND_AL, 0, ORC_ARM_A2, ORC_ARM_A3);
orc_arm_emit_branch (compiler, ORC_ARM_COND_LE, 0);
@@ -75,7 +75,7 @@ orc_arm_emit_epilogue (OrcCompiler *compiler)
regs |= (1<<i);
}
}
- if (regs) orc_arm_emit_pop (compiler, regs);
+ if (regs) orc_arm_emit_pop (compiler, regs, 0U);
orc_arm_emit_bx_lr (compiler);
/* orc_arm_dump_insns (compiler); */
diff --git a/orc/orcprogram-neon.c b/orc/orcprogram-neon.c
index 984b089..cbe79ee 100644
--- a/orc/orcprogram-neon.c
+++ b/orc/orcprogram-neon.c
@@ -34,6 +34,7 @@ void
orc_neon_emit_prologue (OrcCompiler *compiler)
{
unsigned int regs = 0;
+ orc_uint32 vregs = 0;
int i;
orc_compiler_append_code(compiler,".global %s\n", compiler->program->name);
@@ -45,8 +46,15 @@ orc_neon_emit_prologue (OrcCompiler *compiler)
regs |= (1<<i);
}
}
- if (regs) orc_arm_emit_push (compiler, regs);
+ for(i=0;i<32;i++) {
+ if (compiler->used_regs[ORC_VEC_REG_BASE+i] &&
+ compiler->save_regs[ORC_VEC_REG_BASE+i]) {
+ vregs |= (1U << i);
+ }
+ }
+
+ orc_arm_emit_push (compiler, regs, vregs);
}
void
@@ -57,7 +65,7 @@ orc_neon_dump_insns (OrcCompiler *compiler)
orc_arm_emit_add (compiler, ORC_ARM_A2, ORC_ARM_A3, ORC_ARM_A4);
orc_arm_emit_sub (compiler, ORC_ARM_A2, ORC_ARM_A3, ORC_ARM_A4);
- orc_arm_emit_push (compiler, 0x06);
+ orc_arm_emit_push (compiler, 0x06, 0U);
orc_arm_emit_mov (compiler, ORC_ARM_A2, ORC_ARM_A3);
orc_arm_emit_branch (compiler, ORC_ARM_COND_LE, 0);
@@ -73,6 +81,7 @@ orc_neon_emit_epilogue (OrcCompiler *compiler)
{
int i;
unsigned int regs = 0;
+ orc_uint32 vregs = 0;
for(i=0;i<16;i++){
if (compiler->used_regs[ORC_GP_REG_BASE + i] &&
@@ -80,7 +89,15 @@ orc_neon_emit_epilogue (OrcCompiler *compiler)
regs |= (1<<i);
}
}
- if (regs) orc_arm_emit_pop (compiler, regs);
+
+ for(i=0;i<32;i++) {
+ if (compiler->used_regs[ORC_VEC_REG_BASE+i] &&
+ compiler->save_regs[ORC_VEC_REG_BASE+i]) {
+ vregs |= (1U << i);
+ }
+ }
+
+ orc_arm_emit_pop (compiler, regs, vregs);
orc_arm_emit_bx_lr (compiler);
/* arm_dump_insns (compiler); */
@@ -145,6 +162,9 @@ orc_compiler_neon_init (OrcCompiler *compiler)
for(i=4;i<12;i++) {
compiler->save_regs[ORC_GP_REG_BASE+i] = 1;
}
+ for(i=8;i<16;i++) {
+ compiler->save_regs[ORC_VEC_REG_BASE+i] = 1;
+ }
for(i=0;i<ORC_N_REGS;i++){
compiler->alloc_regs[i] = 0;