#include <orc/orcprogram.h>
#include <orc/arm.h>
#include <orc/orcutils.h>
+#include <orc/orcdebug.h>
const char *
}
void
-arm_emit_loadimm (OrcCompiler *compiler, int dest, int imm)
+arm_emit_load_imm (OrcCompiler *compiler, int dest, int imm)
{
uint32_t code;
int shift2;
shift2 = 0;
+#if 0
while (imm && ((imm&3)==0)) {
imm >>= 2;
shift2++;
}
+#endif
+ while (imm && imm > 0xffff) {
+ if ((imm&3) != 0) {
+ ORC_ERROR("bad immediate value");
+ }
+ imm >>= 2;
+ shift2++;
+ }
code = 0xe3a00000;
code |= (dest&0xf) << 12;
}
void
+arm_emit_and_imm (OrcCompiler *compiler, int dest, int src1, int value)
+{
+ uint32_t code;
+
+ code = 0xe2000000;
+ code |= (src1&0xf) << 16;
+ code |= (dest&0xf) << 12;
+ code |= (value) << 0;
+
+ ORC_ASM_CODE(compiler," and %s, %s, #%d\n",
+ arm_reg_name (dest),
+ arm_reg_name (src1),
+ value);
+ arm_emit (compiler, code);
+}
+
+void
arm_emit_sub_imm (OrcCompiler *compiler, int dest, int src1, int value)
{
uint32_t code;
}
void
+arm_emit_cmp (OrcCompiler *compiler, int src1, int src2)
+{
+ uint32_t code;
+
+ code = 0xe1500000;
+ code |= (src1&0xf) << 16;
+ code |= (src2&0xf) << 0;
+
+ ORC_ASM_CODE(compiler," cmp %s, %s\n",
+ arm_reg_name (src1),
+ arm_reg_name (src2));
+ arm_emit (compiler, code);
+}
+
+void
arm_emit_asr_imm (OrcCompiler *compiler, int dest, int src1, int value)
{
uint32_t code;
+ if (value == 0) {
+ ORC_ERROR("bad immediate value");
+ }
code = 0xe1a00040;
code |= (src1&0xf) << 0;
code |= (dest&0xf) << 12;
arm_emit (compiler, code);
}
+void
+arm_emit_store_reg (OrcCompiler *compiler, int dest, int src1, int offset)
+{
+ uint32_t code;
+
+ code = 0xe5800000;
+ code |= (dest&0xf) << 16;
+ code |= (src1&0xf) << 12;
+ code |= offset&0xfff;
+
+ ORC_ASM_CODE(compiler," str %s, [%s, #%d]\n",
+ arm_reg_name (src1),
+ arm_reg_name (dest), offset);
+ arm_emit (compiler, code);
+}
void
void arm_emit (OrcCompiler *compiler, uint32_t insn);
void arm_emit_bx_lr (OrcCompiler *compiler);
const char * arm_reg_name (int reg);
-void arm_emit_loadimm (OrcCompiler *compiler, int dest, int imm);
+void arm_emit_load_imm (OrcCompiler *compiler, int dest, int imm);
void arm_emit_add (OrcCompiler *compiler, int dest, int src1, int src2);
void arm_emit_sub (OrcCompiler *compiler, int dest, int src1, int src2);
void arm_emit_add_imm (OrcCompiler *compiler, int dest, int src1, int value);
+void arm_emit_and_imm (OrcCompiler *compiler, int dest, int src1, int value);
void arm_emit_sub_imm (OrcCompiler *compiler, int dest, int src1, int value);
void arm_emit_asr_imm (OrcCompiler *compiler, int dest, int src1, int value);
void arm_emit_cmp_imm (OrcCompiler *compiler, int src1, int value);
+void arm_emit_cmp (OrcCompiler *compiler, int src1, int src2);
void arm_emit_label (OrcCompiler *compiler, int label);
void arm_emit_push (OrcCompiler *compiler, int regs);
void arm_storew (OrcCompiler *compiler, int dest, int offset, int src1);
void arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offset);
+void arm_emit_store_reg (OrcCompiler *compiler, int src, int dest, int offset);
void arm_do_fixups (OrcCompiler *compiler);
arm_emit_branch (compiler, ARM_COND_LE, 0);
arm_emit_branch (compiler, ARM_COND_AL, 0);
- arm_emit_loadimm (compiler, ARM_A3, 0xa500);
+ arm_emit_load_imm (compiler, ARM_A3, 0xa500);
arm_loadw (compiler, ARM_A3, ARM_A4, 0xa5);
arm_emit_load_reg (compiler, ARM_A3, ARM_A4, 0x5a5);
}
arm_emit_branch (compiler, ARM_COND_LE, 0);
arm_emit_branch (compiler, ARM_COND_AL, 0);
- arm_emit_loadimm (compiler, ARM_A3, 0xa500);
+ arm_emit_load_imm (compiler, ARM_A3, 0xa500);
arm_loadw (compiler, ARM_A3, ARM_A4, 0xa5);
arm_emit_load_reg (compiler, ARM_A3, ARM_A4, 0x5a5);
}
var->size << compiler->loop_shift);
}
+static int
+get_shift (int size)
+{
+ switch (size) {
+ case 1:
+ return 0;
+ case 2:
+ return 1;
+ case 4:
+ return 2;
+ default:
+ ORC_ERROR("bad size %d", size);
+ }
+ return -1;
+}
+
void
orc_compiler_neon_assemble (OrcCompiler *compiler)
{
- int dest_var = orc_compiler_get_dest (compiler);
+ int dest_var;
+ int dest_shift;
+
+ dest_var = orc_compiler_get_dest (compiler);
+ dest_shift = get_shift (compiler->vars[dest_var].size);
compiler->vars[dest_var].is_aligned = FALSE;
neon_emit_prologue (compiler);
+ if (compiler->loop_shift > 0) {
+ arm_emit_load_imm (compiler, ARM_IP, 16);
+
+ arm_emit_load_reg (compiler, ARM_A3, neon_exec_ptr,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor,n));
+ arm_emit_load_reg (compiler, ARM_A2, neon_exec_ptr,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor,arrays[dest_var]));
+ arm_emit_sub (compiler, ARM_IP, ARM_IP, ARM_A2);
+ arm_emit_and_imm (compiler, ARM_IP, ARM_IP, 0xf);
+ if (dest_shift > 0) {
+ arm_emit_asr_imm (compiler, ARM_IP, ARM_IP, dest_shift);
+ }
+
+ arm_emit_cmp (compiler, ARM_IP, ARM_A3);
+ arm_emit_branch (compiler, ARM_COND_LE, 6);
+
+ arm_emit_store_reg (compiler, ARM_IP, neon_exec_ptr,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor,counter1));
+ arm_emit_sub (compiler, ARM_A2, ARM_A3, ARM_IP);
+
+ arm_emit_asr_imm (compiler, ARM_A3, ARM_A2, compiler->loop_shift);
+ arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor,counter2));
+
+ arm_emit_and_imm (compiler, ARM_A3, ARM_A2, (1<<compiler->loop_shift)-1);
+ arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor,counter3));
+
+ arm_emit_branch (compiler, ARM_COND_AL, 7);
+ arm_emit_label (compiler, 6);
+
+ arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor,counter1));
+
+ arm_emit_load_imm (compiler, ARM_A3, 0);
+ arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor,counter2));
+ arm_emit_store_reg (compiler, ARM_A3, neon_exec_ptr,
+ (int)ORC_STRUCT_OFFSET(OrcExecutor,counter3));
+
+ arm_emit_label (compiler, 7);
+ }
+
+
arm_emit_load_reg (compiler, ARM_IP, neon_exec_ptr,
(int)ORC_STRUCT_OFFSET(OrcExecutor,n));
if (compiler->loop_shift > 0) {