diff options
-rw-r--r-- | orc/orcarm.c | 94 | ||||
-rw-r--r-- | orc/orcarm.h | 4 | ||||
-rw-r--r-- | orc/orcprogram-arm.c | 6 | ||||
-rw-r--r-- | orc/orcprogram-neon.c | 26 |
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; |