From a35f744c9d5281f6ba221066747f5a5f76fa3c75 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 18 Sep 2009 23:10:51 +0200 Subject: [PATCH] arm: cleanups and fixes --- orc/orcarm.c | 290 ++++++------- orc/orcarm.h | 165 +++++++- orc/orcprogram-arm.c | 26 +- orc/orcrules-arm.c | 1102 +++++++++++++++++++------------------------------- 4 files changed, 733 insertions(+), 850 deletions(-) diff --git a/orc/orcarm.c b/orc/orcarm.c index a19dc99..39f54ef 100644 --- a/orc/orcarm.c +++ b/orc/orcarm.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,18 @@ * @short_description: code generation for ARM */ +const char * +orc_arm_cond_name (OrcArmCond cond) +{ + static const char *cond_names[] = { + "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "", "" + }; + if (cond < 0 || cond >= 16) { + return "ERROR"; + } + return cond_names[cond&0xf]; +} const char * orc_arm_reg_name (int reg) @@ -103,20 +116,6 @@ orc_arm_emit_pop (OrcCompiler *compiler, int regs) } void -orc_arm_emit_mov (OrcCompiler *compiler, int dest, int src) -{ - uint32_t code; - - code = 0xe1a00000; - code |= (src&0xf) << 0; - code |= (dest&0xf) << 12; - - ORC_ASM_CODE(compiler," mov %s, %s\n", orc_arm_reg_name (dest), orc_arm_reg_name (src)); - - orc_arm_emit (compiler, code); -} - -void orc_arm_emit_label (OrcCompiler *compiler, int label) { ORC_ASM_CODE(compiler,".L%d:\n", label); @@ -147,15 +146,11 @@ orc_arm_do_fixups (OrcCompiler *compiler) diff = ORC_READ_UINT32_LE (ptr) + ((label - ptr) >> 2); ORC_WRITE_UINT32_LE(ptr, (code&0xff000000) | (diff&0x00ffffff)); } - } void orc_arm_emit_branch (OrcCompiler *compiler, int cond, int label) { - static const char *cond_names[] = { - "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", - "hi", "ls", "ge", "lt", "gt", "le", "", "" }; uint32_t code; code = 0x0afffffe; @@ -163,7 +158,7 @@ orc_arm_emit_branch (OrcCompiler *compiler, int cond, int label) orc_arm_add_fixup (compiler, label, 0); orc_arm_emit (compiler, code); - ORC_ASM_CODE(compiler," b%s .L%d\n", cond_names[cond], label); + ORC_ASM_CODE(compiler," b%s .L%d\n", orc_arm_cond_name(cond), label); } void @@ -188,89 +183,6 @@ orc_arm_emit_loadimm (OrcCompiler *compiler, int dest, int imm) } void -orc_arm_emit_add (OrcCompiler *compiler, int dest, int src1, int src2) -{ - uint32_t code; - - code = 0xe0800000; - code |= (src1&0xf) << 16; - code |= (dest&0xf) << 12; - code |= (src2&0xf) << 0; - - ORC_ASM_CODE(compiler," add %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (compiler, code); -} - -void -orc_arm_emit_sub (OrcCompiler *compiler, int dest, int src1, int src2) -{ - uint32_t code; - - code = 0xe0400000; - code |= (src1&0xf) << 16; - code |= (dest&0xf) << 12; - code |= (src2&0xf) << 0; - - ORC_ASM_CODE(compiler," sub %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (compiler, code); -} - -void -orc_arm_emit_add_imm (OrcCompiler *compiler, int dest, int src1, int value) -{ - uint32_t code; - - code = 0xe2800000; - code |= (src1&0xf) << 16; - code |= (dest&0xf) << 12; - code |= (value) << 0; - - ORC_ASM_CODE(compiler," add %s, %s, #%d\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - value); - orc_arm_emit (compiler, code); -} - -void -orc_arm_emit_sub_imm (OrcCompiler *compiler, int dest, int src1, int value) -{ - uint32_t code; - - code = 0xe2500000; - code |= (src1&0xf) << 16; - code |= (dest&0xf) << 12; - code |= (value) << 0; - - ORC_ASM_CODE(compiler," subs %s, %s, #%d\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - value); - orc_arm_emit (compiler, code); -} - -void -orc_arm_emit_cmp_imm (OrcCompiler *compiler, int src1, int value) -{ - uint32_t code; - - code = 0xe3500000; - code |= (src1&0xf) << 16; - code |= (value) << 0; - - ORC_ASM_CODE(compiler," cmp %s, #%d\n", - orc_arm_reg_name (src1), - value); - orc_arm_emit (compiler, code); -} - -void orc_arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offset) { uint32_t code; @@ -286,47 +198,155 @@ orc_arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offset) orc_arm_emit (compiler, code); } - - +/* shifter operands */ +/* 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+ + * |rotimm | immed_8 | + * +-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define arm_so_imm(rot,imm) (((rot)<<8)|(imm)) +/* 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+ + * | Si | St |0| Rm | + * +-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define arm_so_shift_imm(Si,St,Rm) (((Si)<<7)|((St)<<5)|(Rm)) +#define arm_so_rrx_reg(Rm) arm_so_shift_imm(0,ORC_ARM_ROR,Rm) +#define arm_so_reg(Rm) (Rm) +/* 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+ + * | Rs |0| St |1| Rm | + * +-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define arm_so_shift_reg(Rs,St,Rm) (0x008|((Rs)<<8)|((St)<<5)|(Rm)) + +/* data processing instructions */ +/* 3 2 2 2 2 2 2 2 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | cond |0 0|I| opcode|S| Rn | Rd | shifter_operand | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define arm_dp(cond,I,opcode,S,Rn,Rd,So) (((cond)<<28)|((I)<<25)|((opcode)<<21)|((S)<<20)|((Rn)<<16)|((Rd)<<12)|So) +#define arm_dp_reg(cond,opcode,S,Rn,Rd,So) arm_dp (cond,0,opcode,S,Rn,Rd,So) +#define arm_dp_imm(cond,opcode,S,Rn,Rd,So) arm_dp (cond,1,opcode,S,Rn,Rd,So) + +/* + * type 0: {}{s} {}, , #imm (imm = (val>>(shift*2))|(val<<(32-(shift*2)))) + * type 1: {}{s} {}, , + * type 2: {}{s} {}, , , [LSL|LSR|ASR] #imm + * type 3: {}{s} {}, , , [LSL|LSR|ASR] + * type 4: {}{s} {,} , , RRX + */ void -orc_arm_emit_dp_reg (OrcCompiler *compiler, int cond, int opcode, int dest, - int src1, int src2) +orc_arm_emit_dp (OrcCompiler *p, int type, OrcArmCond cond, OrcArmDP opcode, + int S, int Rd, int Rn, int Rm, int shift, int val) { + uint32_t code; + int I = 0; + int shifter_op; + char shifter[100]; + uint32_t imm; + static const char *shift_names[] = { + "LSL", "LSR", "ASR", "ROR" + }; + /* opcodes with Rd */ + static const int op_Rd[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 + }; + /* opcodes using Rn */ + static const int op_Rn[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0 + }; static const char *dp_insn_names[] = { "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc", "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn" }; - static const int shift_expn[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 1, 0, 1 - }; - uint32_t code; - int update = 0; - - code = cond << 28; - code |= opcode << 21; - code |= update << 20; /* update condition codes */ - if (opcode >= 8 && opcode < 12) { - code |= 1 << 20; + + switch (type) { + case 0: + /* #imm */ + imm = val & 0xff; + shifter_op = arm_so_imm (shift, imm); + if (shift > 0) + imm = (imm >> (shift*2)) | (imm << (32-(shift*2))); + snprintf (shifter, sizeof(shifter), "#%08x", imm); + I = 1; + break; + case 1: + /* */ + shifter_op = arm_so_reg (Rm); + snprintf (shifter, sizeof(shifter), "%s", orc_arm_reg_name (Rm)); + break; + case 2: + /* , [LSL|LSR|ASR] #imm */ + shifter_op = arm_so_shift_imm (val,shift,Rm); + snprintf (shifter, sizeof(shifter), "%s, %s #%d", + orc_arm_reg_name (Rm), shift_names[shift], val); + break; + case 3: + /* , [LSL|LSR|ASR] */ + shifter_op = arm_so_shift_reg (val,shift,Rm); + snprintf (shifter, sizeof(shifter), "%s, %s %s", + orc_arm_reg_name (Rm), shift_names[shift], orc_arm_reg_name (val)); + break; + case 4: + /* , RRX */ + shifter_op = arm_so_rrx_reg (Rm); + snprintf (shifter, sizeof(shifter), "%s, RRX", + orc_arm_reg_name (Rm)); + break; + default: + ORC_COMPILER_ERROR(p,"unknown data processing type %d", type); + return; } - code |= (src1&0xf) << 16; - code |= (dest&0xf) << 12; - code |= (src2&0xf) << 0; - - if (shift_expn[opcode]) { - ORC_ASM_CODE(compiler," %s%s %s, %s\n", - dp_insn_names[opcode], - update ? "s" : "", - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); + + if (op_Rd[opcode]) { + if (op_Rn[opcode]) { + /* opcode using Rn */ + code = arm_dp (cond, I, opcode, S, Rn, Rd, shifter_op); + ORC_ASM_CODE(p," %s%s%s %s, %s, %s\n", + dp_insn_names[opcode], orc_arm_cond_name(cond), (S ? "s" : ""), + orc_arm_reg_name (Rd), orc_arm_reg_name (Rn), shifter); + } else { + /* opcode using Rd and val (mov, mvn) */ + code = arm_dp (cond, I, opcode, S, Rn, Rd, shifter_op); + ORC_ASM_CODE(p," %s%s%s %s, %s\n", + dp_insn_names[opcode], orc_arm_cond_name(cond), (S ? "s" : ""), + orc_arm_reg_name (Rd), shifter); + } } else { - ORC_ASM_CODE(compiler," %s%s %s, %s, %s\n", - dp_insn_names[opcode], - update ? "s" : "", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); + /* opcode does not change Rd, change status register (cmp, tst, ..) */ + code = arm_dp (cond, I, opcode, 1, Rn, 0, shifter_op); + ORC_ASM_CODE(p," %s%s %s, %s\n", + dp_insn_names[opcode], orc_arm_cond_name(cond), orc_arm_reg_name (Rn), shifter); } - orc_arm_emit (compiler, code); + orc_arm_emit (p, code); } +/* parallel instructions */ +/* 3 2 2 2 2 2 2 2 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | cond | mode | Rn | Rd |0 0 0 0| op | Rm | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define arm_code_mm(cond,mode,Rn,Rd,op,Rm) (((cond)<<28)|((mode)<<20)|((Rn)<<16)|((Rd)<<12)|((op)<<4)|(Rm)) + +void +orc_arm_emit_mm (OrcCompiler *p, const char *name, OrcArmCond cond, int mode, + int op, int dest, int src1, int src2) +{ + uint32_t code; + + code = arm_code_mm (cond, mode, src1, dest, op, src2); + ORC_ASM_CODE(p," %s%s %s, %s, %s\n", + name, orc_arm_cond_name(cond), + orc_arm_reg_name (dest), + orc_arm_reg_name (src1), + orc_arm_reg_name (src2)); + orc_arm_emit (p, code); +} diff --git a/orc/orcarm.h b/orc/orcarm.h index e1f7dd3..48ce760 100644 --- a/orc/orcarm.h +++ b/orc/orcarm.h @@ -61,26 +61,24 @@ typedef enum { ORC_ARM_COND_AL, } OrcArmCond; +typedef enum { + ORC_ARM_LSL, + ORC_ARM_LSR, + ORC_ARM_ASR, + ORC_ARM_ROR +} OrcArmShift; + void orc_arm_emit (OrcCompiler *compiler, uint32_t insn); void orc_arm_emit_bx_lr (OrcCompiler *compiler); const char * orc_arm_reg_name (int reg); +const char * orc_arm_cond_name (OrcArmCond cond); void orc_arm_emit_loadimm (OrcCompiler *compiler, int dest, int imm); -void orc_arm_emit_add (OrcCompiler *compiler, int dest, int src1, int src2); -void orc_arm_emit_sub (OrcCompiler *compiler, int dest, int src1, int src2); -void orc_arm_emit_add_imm (OrcCompiler *compiler, int dest, int src1, int value); -void orc_arm_emit_sub_imm (OrcCompiler *compiler, int dest, int src1, int value); -void orc_arm_emit_cmp_imm (OrcCompiler *compiler, int src1, int value); - 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_mov (OrcCompiler *compiler, int dest, int src); void orc_arm_emit_branch (OrcCompiler *compiler, int cond, int label); -void orc_arm_emit_dp_reg (OrcCompiler *compiler, int cond, int opcode, int dest, - int src1, int src2); - void orc_arm_loadw (OrcCompiler *compiler, int dest, int src1, int offset); void orc_arm_storew (OrcCompiler *compiler, int dest, int offset, int src1); @@ -88,6 +86,153 @@ void orc_arm_emit_load_reg (OrcCompiler *compiler, int dest, int src1, int offse void orc_arm_do_fixups (OrcCompiler *compiler); +void orc_arm_emit_dp (OrcCompiler *p, int type, OrcArmCond cond, OrcArmDP opcode, + int S, int Rd, int Rn, int Rm, int shift, int val); +void orc_arm_emit_mm (OrcCompiler *p, const char *name, OrcArmCond cond, int mode, + int op, int dest, int src1, int src2); + +/* ALL cpus */ +/* data procesing instructions */ +/* {}{s} {}, , #imm */ +#define orc_arm_emit_and_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_AND,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_eor_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_EOR,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_sub_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_SUB,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_rsb_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_RSB,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_add_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ADD,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_adc_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ADC,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_sbc_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_SBC,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_rsc_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_RSC,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_tst_i(p,cond,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_TST,1, 0,Rn,0,rot,imm) +#define orc_arm_emit_teq_i(p,cond,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_TEQ,1, 0,Rn,0,rot,imm) +#define orc_arm_emit_cmp_i(p,cond,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_CMP,1, 0,Rn,0,rot,imm) +#define orc_arm_emit_cmn_i(p,cond,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_CMN,1, 0,Rn,0,rot,imm) +#define orc_arm_emit_orr_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_ORR,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_mov_i(p,cond,S,Rd,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_MOV,S,Rd, 0,0,rot,imm) +#define orc_arm_emit_bic_i(p,cond,S,Rd,Rn,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_BIC,S,Rd,Rn,0,rot,imm) +#define orc_arm_emit_mvn_i(p,cond,S,Rd,rot,imm) orc_arm_emit_dp(p,0,cond,ORC_ARM_DP_MVN,S,Rd, 0,0,rot,imm) + +/* {}{s} {}, , */ +#define orc_arm_emit_and_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_AND,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_eor_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_EOR,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_sub_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_SUB,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_rsb_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_RSB,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_add_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_ADD,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_adc_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_ADC,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_sbc_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_SBC,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_rsc_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_RSC,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_tst_r(p,cond,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_TST,1, 0,Rn,Rm,0,0) +#define orc_arm_emit_teq_r(p,cond,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_TEQ,1, 0,Rn,Rm,0,0) +#define orc_arm_emit_cmp_r(p,cond,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_CMP,1, 0,Rn,Rm,0,0) +#define orc_arm_emit_cmn_r(p,cond,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_CMN,1, 0,Rn,Rm,0,0) +#define orc_arm_emit_orr_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_ORR,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_mov_r(p,cond,S,Rd,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_MOV,S,Rd, 0,Rm,0,0) +#define orc_arm_emit_bic_r(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_BIC,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_mvn_r(p,cond,S,Rd,Rm) orc_arm_emit_dp(p,1,cond,ORC_ARM_DP_MVN,S,Rd, 0,Rm,0,0) + +/* {}{s} {}, , , [LSL|LSR|ASR] #imm */ +#define orc_arm_emit_and_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_AND,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_eor_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_EOR,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_sub_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_SUB,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_rsb_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_RSB,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_add_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_ADD,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_adc_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_ADC,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_sbc_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_SBC,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_rsc_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_RSC,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_tst_rsi(p,cond,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_TST,1, 0,Rn,Rm,sh,im) +#define orc_arm_emit_teq_rsi(p,cond,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_TEQ,1, 0,Rn,Rm,sh,im) +#define orc_arm_emit_cmp_rsi(p,cond,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_CMP,1, 0,Rn,Rm,sh,im) +#define orc_arm_emit_cmn_rsi(p,cond,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_CMN,1, 0,Rn,Rm,sh,im) +#define orc_arm_emit_orr_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_ORR,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_mov_rsi(p,cond,S,Rd,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_MOV,S,Rd, 0,Rm,sh,im) +#define orc_arm_emit_bic_rsi(p,cond,S,Rd,Rn,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_BIC,S,Rd,Rn,Rm,sh,im) +#define orc_arm_emit_mvn_rsi(p,cond,S,Rd,Rm,sh,im) orc_arm_emit_dp(p,2,cond,ORC_ARM_DP_MVN,S,Rd, 0,Rm,sh,im) + +/* {}{s} {}, , , [LSL|LSR|ASR] */ +#define orc_arm_emit_and_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_AND,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_eor_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_EOR,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_sub_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_SUB,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_rsb_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_RSB,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_add_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_ADD,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_adc_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_ADC,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_sbc_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_SBC,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_rsc_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_RSC,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_tst_rsr(p,cond,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_TST,1, 0,Rn,Rm,sh,Rs) +#define orc_arm_emit_teq_rsr(p,cond,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_TEQ,1, 0,Rn,Rm,sh,Rs) +#define orc_arm_emit_cmp_rsr(p,cond,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_CMP,1, 0,Rn,Rm,sh,Rs) +#define orc_arm_emit_cmn_rsr(p,cond,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_CMN,1, 0,Rn,Rm,sh,Rs) +#define orc_arm_emit_orr_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_ORR,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_mov_rsr(p,cond,S,Rd,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_MOV,S,Rd, 0,Rm,sh,Rs) +#define orc_arm_emit_bic_rsr(p,cond,S,Rd,Rn,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_BIC,S,Rd,Rn,Rm,sh,Rs) +#define orc_arm_emit_mvn_rsr(p,cond,S,Rd,Rm,sh,Rs) orc_arm_emit_dp(p,3,cond,ORC_ARM_DP_MVN,S,Rd, 0,Rm,sh,Rs) + +/* {}{s} {,} , , RRX */ +#define orc_arm_emit_and_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_AND,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_eor_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_EOR,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_sub_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_SUB,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_rsb_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_RSB,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_add_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_ADD,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_adc_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_ADC,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_sbc_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_SBC,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_rsc_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_RSC,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_tst_rrx(p,cond,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_TST,1, 0,Rn,Rm,0,0) +#define orc_arm_emit_teq_rrx(p,cond,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_TEQ,1, 0,Rn,Rm,0,0) +#define orc_arm_emit_cmp_rrx(p,cond,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_CMP,1, 0,Rn,Rm,0,0) +#define orc_arm_emit_cmn_rrx(p,cond,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_CMN,1, 0,Rn,Rm,0,0) +#define orc_arm_emit_orr_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_ORR,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_mov_rrx(p,cond,S,Rd,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_MOV,S,Rd, 0,Rm,0,0) +#define orc_arm_emit_bic_rrx(p,cond,S,Rd,Rn,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_BIC,S,Rd,Rn,Rm,0,0) +#define orc_arm_emit_mvn_rrx(p,cond,S,Rd,Rm) orc_arm_emit_dp(p,4,cond,ORC_ARM_DP_MVN,S,Rd, 0,Rm,0,0) + +/* parallel instructions */ +#define orc_arm_emit_sadd16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"sadd16", cond,0x61,0x1,Rd,Rn,Rm) +#define orc_arm_emit_qadd16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qadd16", cond,0x62,0x1,Rd,Rn,Rm) +#define orc_arm_emit_shadd16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"shadd16", cond,0x63,0x1,Rd,Rn,Rm) +#define orc_arm_emit_uadd16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uadd16", cond,0x65,0x1,Rd,Rn,Rm) +#define orc_arm_emit_uqadd16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uqadd16", cond,0x66,0x1,Rd,Rn,Rm) +#define orc_arm_emit_uhadd16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uhadd16", cond,0x67,0x1,Rd,Rn,Rm) + +#define orc_arm_emit_saddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"saddsubx", cond,0x61,0x3,Rd,Rn,Rm) +#define orc_arm_emit_qaddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qaddsubx", cond,0x62,0x3,Rd,Rn,Rm) +#define orc_arm_emit_shaddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"shaddsubx",cond,0x63,0x3,Rd,Rn,Rm) +#define orc_arm_emit_uaddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uaddsubx", cond,0x65,0x3,Rd,Rn,Rm) +#define orc_arm_emit_uqaddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uqaddsubx",cond,0x66,0x3,Rd,Rn,Rm) +#define orc_arm_emit_uhaddsubx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uhaddsubx",cond,0x67,0x3,Rd,Rn,Rm) + +#define orc_arm_emit_ssubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"ssubaddx", cond,0x61,0x5,Rd,Rn,Rm) +#define orc_arm_emit_qsubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qsubaddx", cond,0x62,0x5,Rd,Rn,Rm) +#define orc_arm_emit_shsubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"shsubaddx",cond,0x63,0x5,Rd,Rn,Rm) +#define orc_arm_emit_usubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"usubaddx", cond,0x65,0x5,Rd,Rn,Rm) +#define orc_arm_emit_uqsubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uqsubaddx",cond,0x66,0x5,Rd,Rn,Rm) +#define orc_arm_emit_uhsubaddx(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uhsubaddx",cond,0x67,0x5,Rd,Rn,Rm) + +#define orc_arm_emit_ssub16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"ssub16", cond,0x61,0x7,Rd,Rn,Rm) +#define orc_arm_emit_qsub16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qsub16", cond,0x62,0x7,Rd,Rn,Rm) +#define orc_arm_emit_shsub16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"shsub16", cond,0x63,0x7,Rd,Rn,Rm) +#define orc_arm_emit_usub16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"usub16", cond,0x65,0x7,Rd,Rn,Rm) +#define orc_arm_emit_uqsub16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uqsub16", cond,0x66,0x7,Rd,Rn,Rm) +#define orc_arm_emit_uhsub16(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uhsub16", cond,0x67,0x7,Rd,Rn,Rm) + +#define orc_arm_emit_sadd8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"sadd8", cond,0x61,0x9,Rd,Rn,Rm) +#define orc_arm_emit_qadd8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qadd8", cond,0x62,0x9,Rd,Rn,Rm) +#define orc_arm_emit_shadd8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"shadd8", cond,0x63,0x9,Rd,Rn,Rm) +#define orc_arm_emit_uadd8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uadd8", cond,0x65,0x9,Rd,Rn,Rm) +#define orc_arm_emit_uqadd8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uqadd8", cond,0x66,0x9,Rd,Rn,Rm) +#define orc_arm_emit_uhadd8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uhadd8", cond,0x67,0x9,Rd,Rn,Rm) + +#define orc_arm_emit_ssub8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"ssub8", cond,0x61,0xf,Rd,Rn,Rm) +#define orc_arm_emit_qsub8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qsub8", cond,0x62,0xf,Rd,Rn,Rm) +#define orc_arm_emit_shsub8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"shsub8", cond,0x63,0xf,Rd,Rn,Rm) +#define orc_arm_emit_usub8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"usub8", cond,0x65,0xf,Rd,Rn,Rm) +#define orc_arm_emit_uqsub8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uqsub8", cond,0x66,0xf,Rd,Rn,Rm) +#define orc_arm_emit_uhsub8(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"uhsub8", cond,0x67,0xf,Rd,Rn,Rm) + +/* misc instructions */ +#define orc_arm_emit_sel(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"sel", cond,0x68,0xb,Rd,Rn,Rm) + +#define orc_arm_emit_qadd(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qadd", cond,0x10,0x5,Rd,Rn,Rm) +#define orc_arm_emit_qsub(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qsub", cond,0x12,0x5,Rd,Rn,Rm) +#define orc_arm_emit_qdadd(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qdadd", cond,0x14,0x5,Rd,Rn,Rm) +#define orc_arm_emit_qdsub(p,cond,Rd,Rn,Rm) orc_arm_emit_mm(p,"qdsub", cond,0x16,0x5,Rd,Rn,Rm) #endif diff --git a/orc/orcprogram-arm.c b/orc/orcprogram-arm.c index 027cf64..b6694d0 100644 --- a/orc/orcprogram-arm.c +++ b/orc/orcprogram-arm.c @@ -50,13 +50,12 @@ orc_arm_emit_prologue (OrcCompiler *compiler) void orc_arm_dump_insns (OrcCompiler *compiler) { - orc_arm_emit_label (compiler, 0); - 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_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_mov (compiler, ORC_ARM_A2, ORC_ARM_A3); + 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); orc_arm_emit_branch (compiler, ORC_ARM_COND_AL, 0); @@ -255,13 +254,13 @@ orc_compiler_orc_arm_assemble (OrcCompiler *compiler) orc_arm_emit_label (compiler, 1); - orc_arm_emit_cmp_imm (compiler, ORC_ARM_IP, 0); + orc_arm_emit_cmp_i (compiler, ORC_ARM_COND_AL, ORC_ARM_IP, 0, 0); orc_arm_emit_branch (compiler, ORC_ARM_COND_EQ, 3); orc_arm_emit_label (compiler, 2); orc_arm_emit_loop (compiler); - orc_arm_emit_sub_imm (compiler, ORC_ARM_IP, ORC_ARM_IP, 1); - orc_arm_emit_cmp_imm (compiler, ORC_ARM_IP, 0); + orc_arm_emit_sub_i (compiler, ORC_ARM_COND_AL, 0, ORC_ARM_IP, ORC_ARM_IP, 0, 1); + orc_arm_emit_cmp_i (compiler, ORC_ARM_COND_AL, ORC_ARM_IP, 0, 0); orc_arm_emit_branch (compiler, ORC_ARM_COND_NE, 2); orc_arm_emit_label (compiler, 3); @@ -317,10 +316,11 @@ orc_arm_emit_loop (OrcCompiler *compiler) rule = insn->rule; if (rule && rule->emit) { - if (compiler->vars[insn->dest_args[0]].alloc != - compiler->vars[insn->src_args[0]].alloc) { - orc_arm_emit_mov (compiler, compiler->vars[insn->src_args[0]].alloc, - compiler->vars[insn->dest_args[0]].alloc); + int src = ORC_SRC_ARG (compiler, insn, 0); + int dest = ORC_DEST_ARG (compiler, insn, 0); + + if (dest != src) { + orc_arm_emit_mov_r (compiler, ORC_ARM_COND_AL, 0, src, dest); } rule->emit (compiler, rule->emit_user, insn); } else { @@ -347,9 +347,9 @@ orc_arm_emit_loop (OrcCompiler *compiler) if (compiler->vars[k].vartype == ORC_VAR_TYPE_SRC || compiler->vars[k].vartype == ORC_VAR_TYPE_DEST) { if (compiler->vars[k].ptr_register) { - orc_arm_emit_add_imm (compiler, - compiler->vars[k].ptr_register, + orc_arm_emit_add_i (compiler, ORC_ARM_COND_AL, 0, compiler->vars[k].ptr_register, + compiler->vars[k].ptr_register, 0, compiler->vars[k].size << compiler->loop_shift); } else { //orc_arm_emit_add_imm_memoffset (compiler, orc_arm_ptr_size, diff --git a/orc/orcrules-arm.c b/orc/orcrules-arm.c index fb058f7..daf41af 100644 --- a/orc/orcrules-arm.c +++ b/orc/orcrules-arm.c @@ -12,136 +12,27 @@ #include #include -#define COND_EQ 0x0 -#define COND_NE 0x1 -#define COND_CS 0x2 -#define COND_HS 0x2 -#define COND_CC 0x3 -#define COND_LO 0x3 -#define COND_MI 0x4 -#define COND_PL 0x5 -#define COND_VS 0x6 -#define COND_VC 0x7 -#define COND_HI 0x8 -#define COND_LS 0x9 -#define COND_GE 0xa -#define COND_LT 0xb -#define COND_GT 0xc -#define COND_LE 0xd -#define COND_AL 0xe - -/* shifter operands */ -/* 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+ - * |rotimm | immed_8 | - * +-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define arm_so_imm(rot,imm) (((rot)<<8)|(imm)) -/* 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+ - * | Si | St |0| Rm | - * +-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define arm_so_shift_imm(Si,St,Rm) (((Si)<<7)|((St)<<5)|(Rm)) -#define SHIFT_LSL 0 -#define SHIFT_LSR 1 -#define SHIFT_ASR 2 -#define SHIFT_ROR 3 -#define arm_so_rrx_reg(Rm) arm_so_shift_imm(0,SHIFT_ROR,Rm) -#define arm_so_reg(Rm) (Rm) -/* 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+ - * | Rs |0| St |1| Rm | - * +-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define arm_so_shift_reg(Rs,St,Rm) (0x008|((Rs)<<8)|((St)<<5)|(Rm)) - -/* data processing instructions */ -/* 3 2 2 2 2 2 2 2 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | cond |0 0|I| opcode|S| Rn | Rd | shifter_operand | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define arm_dp(cond,I,opcode,S,Rn,Rd,So) (((cond)<<28)|((I)<<25)|((opcode)<<21)|((S)<<20)|((Rn)<<16)|((Rd)<<12)|So) -#define arm_dp_reg(cond,opcode,S,Rn,Rd,So) arm_dp (cond,0,opcode,S,Rn,Rd,So) -#define arm_dp_imm(cond,opcode,S,Rn,Rd,So) arm_dp (cond,1,opcode,S,Rn,Rd,So) -#define DP_AND 0x0 -#define DP_EOR 0x1 -#define DP_SUB 0x2 -#define DP_RSB 0x3 -#define DP_ADD 0x4 -#define DP_ADC 0x5 -#define DP_SBC 0x6 -#define DP_RSC 0x7 -#define DP_TST 0x8 -#define DP_TEQ 0x9 -#define DP_CMP 0xa -#define DP_CMN 0xb -#define DP_ORR 0xc -#define DP_MOV 0xd -#define DP_BIC 0xe -#define DP_MVN 0xf - -#define BINARY_DP(opcode,insn_name,dp_op) \ +#define BINARY_DP(opcode,insn_name) \ static void \ arm_rule_ ## opcode (OrcCompiler *p, void *user, OrcInstruction *insn) \ { \ - uint32_t code; \ int src1 = ORC_SRC_ARG (p, insn, 0); \ int src2 = ORC_SRC_ARG (p, insn, 1); \ int dest = ORC_DEST_ARG (p, insn, 0); \ \ - code = arm_dp_reg (COND_AL, dp_op, 0, src1, dest, arm_so_reg (src2));\ - ORC_ASM_CODE(p," %s %s, %s, %s\n", \ - insn_name, \ - orc_arm_reg_name (dest), \ - orc_arm_reg_name (src1), \ - orc_arm_reg_name (src2)); \ - orc_arm_emit (p, code); \ + orc_arm_emit_ ##insn_name## _r (p, ORC_ARM_COND_AL, 0, \ + dest, src1, src2); \ } -/* parallel instructions */ -/* 3 2 2 2 2 2 2 2 1 1 1 1 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | cond | mode | Rn | Rd |0 0 0 0| op | Rm | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define arm_code_mm(cond,mode,Rn,Rd,op,Rm) (((cond)<<28)|((mode)<<20)|((Rn)<<16)|((Rd)<<12)|((op)<<4)|(Rm)) -#define MM_MODE_S 0x61 -#define MM_MODE_Q 0x62 -#define MM_MODE_SH 0x63 -#define MM_MODE_U 0x65 -#define MM_MODE_UQ 0x66 -#define MM_MODE_UH 0x67 - -#define MM_OP_ADD16 0x1 -#define MM_OP_ADDSUBX 0x3 -#define MM_OP_SUBADDX 0x5 -#define MM_OP_SUB16 0x7 -#define MM_OP_ADD8 0x9 -#define MM_OP_SUB8 0xf - -#define BINARY_MM(opcode,insn_name,mm_op,mm_mode) \ +#define BINARY_MM(opcode,insn_name) \ static void \ arm_rule_ ## opcode (OrcCompiler *p, void *user, OrcInstruction *insn) \ { \ - uint32_t code; \ int src1 = ORC_SRC_ARG (p, insn, 0); \ int src2 = ORC_SRC_ARG (p, insn, 1); \ int dest = ORC_DEST_ARG (p, insn, 0); \ \ - code = arm_code_mm (COND_AL, mm_mode, src1, dest, mm_op, src2); \ - ORC_ASM_CODE(p," %s %s, %s, %s\n", \ - insn_name, \ - orc_arm_reg_name (dest), \ - orc_arm_reg_name (src1), \ - orc_arm_reg_name (src2)); \ - orc_arm_emit (p, code); \ + orc_arm_emit_##insn_name (p, ORC_ARM_COND_AL, dest, src1, src2); \ } #define arm_emit_sxtb(cond,Rd,rot,Rm) (0x06af0070|((cond)<<28)|((Rd)<<12)|((rot)<<10)|(Rm)) @@ -183,71 +74,75 @@ orc_arm_storew (OrcCompiler *compiler, int dest, int offset, int src1) orc_arm_emit (compiler, code); } +void +orc_arm_emit_mov_iw (OrcCompiler *p, int cond, int dest, int val, int loop) +{ + int shift = 0; + + while (val && ((val & 3) == 0)) { + val >>= 2; + shift++; + } + /* dest = val */ + orc_arm_emit_mov_i (p, cond, 0, dest, shift, val); + if (loop > 1) + /* 2 words: dest |= dest << 16 */ + orc_arm_emit_orr_rsi (p, cond, 0, dest, dest, dest, ORC_ARM_LSL, 16); +} + +void +orc_arm_emit_mov_ib (OrcCompiler *p, int cond, int dest, int val, int loop) +{ + int shift = 0; + + while (val && ((val & 3) == 0)) { + val >>= 2; + shift++; + } + /* 1 byte */ + orc_arm_emit_mov_i (p, cond, 0, dest, shift, val); + if (loop > 1) + /* 2 bytes: dest |= dest << 8 */ + orc_arm_emit_orr_rsi (p, cond, 0, dest, dest, dest, ORC_ARM_LSL, 8); + if (loop > 2) + /* 4 bytes: dest |= dest << 16 */ + orc_arm_emit_orr_rsi (p, cond, 0, dest, dest, dest, ORC_ARM_LSL, 16); +} + +/* byte instructions */ static void arm_rule_absX (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); int tmp = p->tmpreg; int type = ORC_PTR_TO_INT(user); - code = arm_dp_imm (COND_AL, DP_MOV, 0, 0, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mov %s, #0\n", - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0); if (type == 0) { /* negate tmp = 0 - src1 */ - code = arm_code_mm (COND_AL, MM_MODE_S, dest, tmp, MM_OP_SUB8, src1); - ORC_ASM_CODE(p," ssub8 %s, %s, %s\n", - orc_arm_reg_name (tmp), - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); - + orc_arm_emit_ssub8 (p, ORC_ARM_COND_AL, tmp, dest, src1); /* check sign dest = src1 - 0 */ - code = arm_code_mm (COND_AL, MM_MODE_S, src1, dest, MM_OP_SUB8, dest); - ORC_ASM_CODE(p," ssub8 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + orc_arm_emit_ssub8 (p, ORC_ARM_COND_AL, dest, src1, dest); } else { /* negate tmp = 0 - src1 */ - code = arm_code_mm (COND_AL, MM_MODE_S, dest, tmp, MM_OP_SUB16, src1); - ORC_ASM_CODE(p," ssub16 %s, %s, %s\n", - orc_arm_reg_name (tmp), - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); - + orc_arm_emit_ssub16 (p, ORC_ARM_COND_AL, tmp, dest, src1); /* check sign dest = src1 - 0 */ - code = arm_code_mm (COND_AL, MM_MODE_S, src1, dest, MM_OP_SUB16, dest); - ORC_ASM_CODE(p," ssub16 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + orc_arm_emit_ssub16 (p, ORC_ARM_COND_AL, dest, src1, dest); } /* take positive or negative values */ - code = arm_code_mm (COND_AL, 0x68, src1, dest, 0xb, tmp); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (tmp)); - orc_arm_emit (p, code); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src1, tmp); } -BINARY_MM (addb, "sadd8", MM_OP_ADD8, MM_MODE_S); -BINARY_MM (addssb, "qadd8", MM_OP_ADD8, MM_MODE_Q); -BINARY_MM (addusb, "uqadd8", MM_OP_ADD8, MM_MODE_UQ); -BINARY_DP (andX, "and", DP_AND); -BINARY_DP (andnX, "bic", DP_BIC); +BINARY_MM (addb, sadd8); +BINARY_MM (addssb, qadd8); +BINARY_MM (addusb, uqadd8); +BINARY_DP (andX, and); +BINARY_DP (andnX, bic); static void arm_rule_avgX (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int mask = p->tmpreg; @@ -258,318 +153,150 @@ arm_rule_avgX (OrcCompiler *p, void *user, OrcInstruction *insn) /* signed variant, make a mask, FIXME, instruction constants */ if (type >= 2) { /* mask for word 0x80008000 */ - code = arm_dp_reg (COND_AL, DP_MOV, 0, 0, mask, arm_so_imm (4,8)); - ORC_ASM_CODE(p," mov %s, #0x80000000\n", - orc_arm_reg_name (mask)); - orc_arm_emit (p, code); - - code = arm_dp_imm (COND_AL, DP_ORR, 0, 0, mask, arm_so_shift_imm (16,SHIFT_LSR,mask)); - ORC_ASM_CODE(p," orr %s, %s, %s, LSR #16\n", - orc_arm_reg_name (mask), - orc_arm_reg_name (mask), - orc_arm_reg_name (mask)); - orc_arm_emit (p, code); + orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, mask, 4, 8); + orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, mask, mask, mask, ORC_ARM_LSR, 16); if (type >= 3) { /* mask for byte 0x80808080 */ - code = arm_dp_imm (COND_AL, DP_ADD, 0, 0, mask, arm_so_shift_imm (8,SHIFT_LSR,mask)); - ORC_ASM_CODE(p," orr %s, %s, %s, LSR #8\n", - orc_arm_reg_name (mask), - orc_arm_reg_name (mask), - orc_arm_reg_name (mask)); - orc_arm_emit (p, code); + orc_arm_emit_orr_rsi (p, ORC_ARM_COND_AL, 0, mask, mask, mask, ORC_ARM_LSR, 8); } - } - if (type >= 2) { /* signed variant, bias the inputs */ - code = arm_dp_reg (COND_AL, DP_EOR, 0, src1, src1, arm_so_reg (mask)); - ORC_ASM_CODE(p," eor %s, %s, %s\n", - orc_arm_reg_name (src1), - orc_arm_reg_name (src1), - orc_arm_reg_name (mask)); - orc_arm_emit (p, code); - - code = arm_dp_reg (COND_AL, DP_EOR, 0, src2, src2, arm_so_reg (mask)); - ORC_ASM_CODE(p," eor %s, %s, %s\n", - orc_arm_reg_name (src2), - orc_arm_reg_name (src2), - orc_arm_reg_name (mask)); - orc_arm_emit (p, code); + orc_arm_emit_eor_r (p, ORC_ARM_COND_AL, 0, src1, src1, mask); + orc_arm_emit_eor_r (p, ORC_ARM_COND_AL, 0, src2, src2, mask); } /* dest = (s1 | s2) - (((s1 ^ s2) & ~(0x1 >>> (shift*2))) >> 1) */ - code = arm_dp_reg (COND_AL, DP_EOR, 0, src1, dest, arm_so_reg (src2)); - ORC_ASM_CODE(p," eor %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_dp_reg (COND_AL, DP_ORR, 0, src1, mask, arm_so_reg (src2)); - ORC_ASM_CODE(p," orr %s, %s, %s\n", - orc_arm_reg_name (tmp), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + /* (s1 | s2) */ + orc_arm_emit_orr_r (p, ORC_ARM_COND_AL, 0, tmp, src1, src2); + /* (s1 ^ s2) */ + orc_arm_emit_eor_r (p, ORC_ARM_COND_AL, 0, dest, src1, src2); /* clear the bits we will shift into view in the next instruction, FIXME, we * need instruction wide constants */ if (type <= 1) { - code = arm_dp_imm (COND_AL, DP_BIC, 0, dest, dest, arm_so_imm (8,1)); - ORC_ASM_CODE(p," bic %s, %s, #0x00010000\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); - + /* clear 0x00010000 */ + orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 8, 1); if (type == 0) { - code = arm_dp_imm (COND_AL, DP_BIC, 0, dest, dest, arm_so_imm (12,1)); - ORC_ASM_CODE(p," bic %s, %s, #0x00000100\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); - - code = arm_dp_imm (COND_AL, DP_BIC, 0, dest, dest, arm_so_imm (4,1)); - ORC_ASM_CODE(p," bic %s, %s, #0x01000000\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* clear 0x00000100 */ + orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 12, 1); + /* clear 0x01000000 */ + orc_arm_emit_bic_i (p, ORC_ARM_COND_AL, 0, dest, dest, 4, 1); } } else if (type >= 2) { /* already have a mask, use it here */ - code = arm_dp_imm (COND_AL, DP_BIC, 0, dest, dest, arm_so_shift_imm (7,SHIFT_LSR,mask)); - ORC_ASM_CODE(p," bic %s, %s, %s, LSR #7\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (dest), - orc_arm_reg_name (mask)); - orc_arm_emit (p, code); + orc_arm_emit_bic_rsi (p, ORC_ARM_COND_AL, 0, dest, dest, mask, ORC_ARM_LSR, 7); } - code = arm_dp_reg (COND_AL, DP_SUB, 0, mask, dest, arm_so_shift_imm (1,SHIFT_LSR,dest)); - ORC_ASM_CODE(p," sub %s, %s, %s LSR #1\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (tmp), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* do final right shift and subtraction */ + orc_arm_emit_sub_rsi (p, ORC_ARM_COND_AL, 0, dest, tmp, dest, ORC_ARM_LSR, 1); if (type >= 2) { - /* signed variant, unbias again */ - code = arm_dp_reg (COND_AL, DP_EOR, 0, src1, src1, arm_so_reg (mask)); - ORC_ASM_CODE(p," eor %s, %s, %s\n", - orc_arm_reg_name (src1), - orc_arm_reg_name (src1), - orc_arm_reg_name (mask)); - orc_arm_emit (p, code); - code = arm_dp_reg (COND_AL, DP_EOR, 0, src2, src2, arm_so_reg (mask)); - ORC_ASM_CODE(p," eor %s, %s, %s\n", - orc_arm_reg_name (src2), - orc_arm_reg_name (src2), - orc_arm_reg_name (mask)); - orc_arm_emit (p, code); + /* signed variant, unbias input again */ + orc_arm_emit_eor_r (p, ORC_ARM_COND_AL, 0, src1, src1, mask); + orc_arm_emit_eor_r (p, ORC_ARM_COND_AL, 0, src2, src2, mask); } } static void arm_rule_cmpeqX (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); int tmp = p->tmpreg; - int type = ORC_PTR_TO_INT(user); + int size = ORC_PTR_TO_INT(user); /* bytes that are equal will have all bits 0 */ - code = arm_dp_reg (COND_AL, DP_EOR, 0, src1, dest, arm_so_reg (src1)); - ORC_ASM_CODE(p," eor %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + orc_arm_emit_eor_r (p, ORC_ARM_COND_AL, 0, tmp, src1, src2); - /* dest = 0 - dest, set GE flags for 0 bytes */ - if (type == 0) { - code = arm_code_mm (COND_AL, MM_MODE_U, src1, dest, MM_OP_SUB8, dest); - ORC_ASM_CODE(p," usub8 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* clear dest register */ + orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0); + + /* tmp = 0 - tmp, set GE flags for 0 bytes */ + if (size == 1) { + orc_arm_emit_usub8 (p, ORC_ARM_COND_AL, tmp, dest, tmp); } else { - code = arm_code_mm (COND_AL, MM_MODE_U, src1, dest, MM_OP_SUB16, dest); - ORC_ASM_CODE(p," usub16 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + orc_arm_emit_usub16 (p, ORC_ARM_COND_AL, tmp, dest, tmp); } - /* clear dest register */ - code = arm_dp_imm (COND_AL, DP_MOV, 0, 0, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mov %s, #0\n", - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); - /* make 0xffffffff in tmp */ - code = arm_dp_imm (COND_AL, DP_MVN, 0, 0, tmp, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mvn %s, #0\n", - orc_arm_reg_name (tmp)); - orc_arm_emit (p, code); + orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, tmp, 0, 0); /* set 0xff for 0 bytes, 0x00 otherwise */ - code = arm_code_mm (COND_AL, 0x68, tmp, dest, 0xb, dest); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (tmp), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, tmp, dest); } static void arm_rule_cmpgtsX (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); int tmp = p->tmpreg; - int type = ORC_PTR_TO_INT(user); + int size = ORC_PTR_TO_INT(user); /* dest = src2 - src1, set GE flags for src2 >= src1 */ - if (type == 0) { - code = arm_code_mm (COND_AL, MM_MODE_S, src2, dest, MM_OP_SUB8, src1); - ORC_ASM_CODE(p," ssub8 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + if (size == 1) { + orc_arm_emit_ssub8 (p, ORC_ARM_COND_AL, dest, src2, src1); } else { - code = arm_code_mm (COND_AL, MM_MODE_S, src2, dest, MM_OP_SUB16, src1); - ORC_ASM_CODE(p," ssub16 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_ssub16 (p, ORC_ARM_COND_AL, dest, src2, src1); } /* clear dest register */ - code = arm_dp_imm (COND_AL, DP_MOV, 0, 0, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mov %s, #0\n", - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); - + orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0); /* make 0xffffffff in tmp */ - code = arm_dp_imm (COND_AL, DP_MVN, 0, 0, tmp, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mvn %s, #0\n", - orc_arm_reg_name (tmp)); + orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, tmp, 0, 0); /* set 0x00 for src2 >= src1 bytes, 0xff if src2 < src1 */ - code = arm_code_mm (COND_AL, 0x68, dest, dest, 0xb, tmp); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (dest), - orc_arm_reg_name (tmp)); - orc_arm_emit (p, code); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, dest, tmp); } static void arm_rule_copyX (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_dp_reg (COND_AL, DP_MOV, 0, 0, dest, arm_so_reg (src1)); - ORC_ASM_CODE(p," mov %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_mov_r (p, ORC_ARM_COND_AL, 0, dest, src1); } static void arm_rule_maxsb (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_code_mm (COND_AL, MM_MODE_S, src1, dest, MM_OP_SUB8, src2); - ORC_ASM_CODE(p," ssub8 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_code_mm (COND_AL, 0x68, src1, dest, 0xb, src2); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + orc_arm_emit_ssub8 (p, ORC_ARM_COND_AL, dest, src1, src2); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src1, src2); } static void arm_rule_maxub (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_code_mm (COND_AL, MM_MODE_U, src1, dest, MM_OP_SUB8, src2); - ORC_ASM_CODE(p," usub8 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_code_mm (COND_AL, 0x68, src1, dest, 0xb, src2); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + orc_arm_emit_usub8 (p, ORC_ARM_COND_AL, dest, src1, src2); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src1, src2); } static void arm_rule_minsb (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_code_mm (COND_AL, MM_MODE_S, src1, dest, MM_OP_SUB8, src2); - ORC_ASM_CODE(p," ssub8 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_code_mm (COND_AL, 0x68, src2, dest, 0xb, src1); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_ssub8 (p, ORC_ARM_COND_AL, dest, src1, src2); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src2, src1); } static void arm_rule_minub (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_code_mm (COND_AL, MM_MODE_U, src1, dest, MM_OP_SUB8, src2); - ORC_ASM_CODE(p," usub8 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_code_mm (COND_AL, 0x68, src2, dest, 0xb, src1); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_usub8 (p, ORC_ARM_COND_AL, dest, src1, src2); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src2, src1); } #if 0 @@ -577,214 +304,312 @@ BINARY_SB(mullb, "(%s * %s) & 0xff") BINARY_SB(mulhsb, "(%s * %s) >> 8") BINARY_UB(mulhub, "((uint32_t)(uint8_t)%s * (uint32_t)(uint8_t)%s) >> 8") #endif -BINARY_DP (orX, "orr", DP_ORR); +BINARY_DP (orX, orr); static void -arm_rule_shift (OrcCompiler *p, void *user, OrcInstruction *insn) +arm_rule_shlX (OrcCompiler *p, void *user, OrcInstruction *insn) { - /* FIXME not parallel */ - uint32_t code; + /* degrades nicely to trivial shift when not doing parallel shifts */ int src1 = ORC_SRC_ARG (p, insn, 0); - int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - int type = ORC_PTR_TO_INT(user); - const char *codes[] = { NULL, "sxtb", "uxtb", NULL, NULL, "sxth", "uxth", NULL }; - const int opcodes[] = { 0, 0x06af0070, 0x06ef0070, 0, 0, 0x06bf0070, 0x06ff0070, 0 }; - const char *shifts[] = { "LSL", "ASR", "LSR", NULL }; - const int opshifts[] = { SHIFT_LSL, SHIFT_ASR, SHIFT_LSR, 0 }; - int shtype = type & 3; - - if (codes[type]) { - code = (opcodes[type]|((COND_AL)<<28)|((src1)<<12)|(src1)); - ORC_ASM_CODE(p," %s %s, %s\n", - codes[type], - orc_arm_reg_name (src1), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + int mask = p->tmpreg; + int src2type = ORC_SRC_TYPE (p, insn, 1); + int size = ORC_PTR_TO_INT(user); + int loop = 4 / size; /* number of items in one register */ + + if (src2type == ORC_VAR_TYPE_CONST) { + int val = ORC_SRC_VAL (p, insn, 1); + + if (loop > 1 && size != 4 && val < 5) { + for (;val; val--) { + /* small values, do a series of additions, we need at least 5 + * instructions for the generic case below. */ + if (size == 1) + orc_arm_emit_uadd8 (p, ORC_ARM_COND_AL, dest, src1, src1); + else + orc_arm_emit_uadd16 (p, ORC_ARM_COND_AL, dest, src1, src1); + } + } + else { + /* bigger values, shift and mask out excess bits */ + if (val >= size) { + /* too big, clear all */ + orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0); + } else if (val > 0) { + if (loop > 1 && size < 4) { + /* shift, note that we skip the next instructions when 0 */ + orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSL, val); + if (size == 1) + /* make loop * 0x80 */ + orc_arm_emit_mov_ib (p, ORC_ARM_COND_NE, mask, 0x80, loop); + else + /* make loop * 0x8000 */ + orc_arm_emit_mov_iw (p, ORC_ARM_COND_NE, mask, 0x8000, loop); + /* make mask, this mask has enough bits but is shifted one position to the right */ + orc_arm_emit_sub_rsi (p, ORC_ARM_COND_NE, 0, mask, mask, mask, ORC_ARM_LSR, val); + /* clear upper bits */ + orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, mask, ORC_ARM_LSL, 1); + } else { + orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_LSL, val); + } + } + } + } else if (src2type == ORC_VAR_TYPE_PARAM) { + int src2 = ORC_SRC_ARG (p, insn, 1); + + if (loop > 1 && size < 4) { + /* shift with register value, note that we skip the next instructions when 0 */ + orc_arm_emit_mov_rsr (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSL, src2); + if (size == 1) + /* make loop * 0x80 */ + orc_arm_emit_mov_ib (p, ORC_ARM_COND_NE, mask, 0x80, loop); + else + /* make loop * 0x8000 */ + orc_arm_emit_mov_iw (p, ORC_ARM_COND_NE, mask, 0x8000, loop); + /* make mask */ + orc_arm_emit_sub_rsr (p, ORC_ARM_COND_NE, 0, mask, mask, mask, ORC_ARM_LSR, src2); + /* clear bits */ + orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, mask, ORC_ARM_LSL, 1); + } else { + orc_arm_emit_mov_rsr (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_LSL, src2); + } + } else { + ORC_COMPILER_ERROR(p,"rule only works with constants or parameters"); } +} - if (ORC_SRC_TYPE (p, insn, 1) == ORC_VAR_TYPE_CONST) { +static void +arm_rule_shrsX (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + /* degrades nicely to trivial shift when not doing parallel shifts */ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int mask = p->tmpreg; + int tmp = ORC_ARM_IP; + int src2type = ORC_SRC_TYPE (p, insn, 1); + int size = ORC_PTR_TO_INT(user); + int loop = 4 / size; /* number of items in one register */ + + if (src2type == ORC_VAR_TYPE_CONST) { int val = ORC_SRC_VAL (p, insn, 1); - code = arm_dp_reg (COND_AL, DP_MOV, 0, 0, dest, - arm_so_shift_imm (val, opshifts[shtype], src1)); - ORC_ASM_CODE(p," mov %s, %s, %s #%d\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - shifts[shtype], - val); - orc_arm_emit (p, code); - } else if (ORC_SRC_TYPE (p, insn, 1) == ORC_VAR_TYPE_PARAM) { - code = arm_dp_reg (COND_AL, DP_MOV, 0, 0, dest, - arm_so_shift_imm (src2, opshifts[shtype], src1)); - ORC_ASM_CODE(p," mov %s, %s, %s %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - shifts[shtype], - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + if (val > 0) { + /* clamp max shift so we can sign extend */ + if (val >= size) + val = size - 1; + + /* shift */ + if (size < 4) { + if (size == 1) + /* make loop * 80, position of sign bit after shift */ + orc_arm_emit_mov_ib (p, ORC_ARM_COND_AL, mask, 0x80, loop); + else + /* make loop * 8000 */ + orc_arm_emit_mov_iw (p, ORC_ARM_COND_AL, mask, 0x8000, loop); + /* make mask, save in tmp, we need the original mask */ + orc_arm_emit_sub_rsi (p, ORC_ARM_COND_AL, 0, tmp, mask, mask, ORC_ARM_LSR, val); + + /* do the shift */ + orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSR, val); + /* clear upper bits */ + orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, tmp, ORC_ARM_LSL, 1); + + /* flip sign bit */ + orc_arm_emit_eor_r (p, ORC_ARM_COND_NE, 0, dest, dest, mask); + /* extend sign bits */ + if (size == 1) + orc_arm_emit_usub8 (p, ORC_ARM_COND_NE, dest, dest, mask); + else + orc_arm_emit_usub16 (p, ORC_ARM_COND_NE, dest, dest, mask); + } else { + /* full word shift */ + orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_ASR, val); + } + } + } else if (src2type == ORC_VAR_TYPE_PARAM) { + int src2 = ORC_SRC_ARG (p, insn, 1); + + if (size < 4) { + if (size == 1) + /* make loop * 0x80 */ + orc_arm_emit_mov_ib (p, ORC_ARM_COND_AL, mask, 0x80, loop); + else + /* make loop * 0x8000 */ + orc_arm_emit_mov_iw (p, ORC_ARM_COND_AL, mask, 0x8000, loop); + /* make mask */ + orc_arm_emit_sub_rsr (p, ORC_ARM_COND_AL, 0, tmp, mask, mask, ORC_ARM_LSR, src2); + + /* do the shift */ + orc_arm_emit_mov_rsr (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSR, src2); + /* clear upper bits */ + orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, tmp, ORC_ARM_LSL, 1); + + /* flip sign bit */ + orc_arm_emit_eor_r (p, ORC_ARM_COND_NE, 0, dest, dest, mask); + /* extend sign bits */ + if (size == 1) + orc_arm_emit_usub8 (p, ORC_ARM_COND_NE, dest, dest, mask); + else + orc_arm_emit_usub16 (p, ORC_ARM_COND_NE, dest, dest, mask); + } else { + /* full word shift with register value */ + orc_arm_emit_mov_rsr (p, ORC_ARM_COND_AL, 0, dest, dest, ORC_ARM_ASR, src2); + } } else { ORC_COMPILER_ERROR(p,"rule only works with constants or parameters"); } } + +static void +arm_rule_shruX (OrcCompiler *p, void *user, OrcInstruction *insn) +{ + /* degrades nicely to trivial shift when not doing parallel shifts */ + int src1 = ORC_SRC_ARG (p, insn, 0); + int dest = ORC_DEST_ARG (p, insn, 0); + int mask = p->tmpreg; + int src2type = ORC_SRC_TYPE (p, insn, 1); + int size = ORC_PTR_TO_INT(user); + int loop = 4 / size; /* number of items in one register */ + + if (src2type == ORC_VAR_TYPE_CONST) { + int val = ORC_SRC_VAL (p, insn, 1); + + /* shift and mask out excess bits */ + if (val >= size) { + /* too big, clear all */ + orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, dest, 0, 0); + } else if (val > 0) { + if (size < 4) { + /* do the shift */ + orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSR, val); + + if (size == 1) + /* make loop * 0x80 */ + orc_arm_emit_mov_ib (p, ORC_ARM_COND_NE, mask, 0x80, loop); + else + /* make loop * 0x8000 */ + orc_arm_emit_mov_iw (p, ORC_ARM_COND_NE, mask, 0x8000, loop); + /* make mask */ + orc_arm_emit_sub_rsi (p, ORC_ARM_COND_NE, 0, mask, mask, mask, ORC_ARM_LSR, val); + + /* clear upper bits */ + orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, mask, ORC_ARM_LSL, 1); + } else { + orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_LSR, val); + } + } + } else if (src2type == ORC_VAR_TYPE_PARAM) { + int src2 = ORC_SRC_ARG (p, insn, 1); + + if (size < 4) { + /* shift with register value */ + orc_arm_emit_mov_rsr (p, ORC_ARM_COND_AL, 1, dest, src1, ORC_ARM_LSR, src2); + + if (size == 1) + /* make loop * 0x80 */ + orc_arm_emit_mov_ib (p, ORC_ARM_COND_NE, mask, 0x80, loop); + else + /* make loop * 0x8000 */ + orc_arm_emit_mov_iw (p, ORC_ARM_COND_NE, mask, 0x8000, loop); + /* mask mask */ + orc_arm_emit_sub_rsr (p, ORC_ARM_COND_NE, 0, mask, mask, mask, ORC_ARM_LSR, src2); + + /* clear bits */ + orc_arm_emit_bic_rsi (p, ORC_ARM_COND_NE, 0, dest, dest, mask, ORC_ARM_LSL, 1); + } else { + /* shift with register value */ + orc_arm_emit_mov_rsr (p, ORC_ARM_COND_AL, 0, dest, src1, ORC_ARM_LSR, src2); + } + } else { + ORC_COMPILER_ERROR(p,"rule only works with constants or parameters"); + } +} + static void arm_rule_signX (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); int zero = p->tmpreg; int ones = ORC_ARM_IP; int tmp = ORC_ARM_V8; int type = ORC_PTR_TO_INT(user); - const char *codes[] = { "ssub8", "ssub16" }; - const int opcodes[] = { MM_OP_SUB8, MM_OP_SUB16 }; /* make 0 */ - code = arm_dp_imm (COND_AL, DP_MOV, 0, 0, zero, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mov %s, #0\n", orc_arm_reg_name (zero)); - orc_arm_emit (p, code); - + orc_arm_emit_mov_i (p, ORC_ARM_COND_AL, 0, zero, 0, 0); /* make 0xffffffff */ - code = arm_dp_imm (COND_AL, DP_MVN, 0, 0, ones, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mvn %s, #0\n", orc_arm_reg_name (ones)); - orc_arm_emit (p, code); + orc_arm_emit_mvn_i (p, ORC_ARM_COND_AL, 0, ones, 0, 0); /* dest = src1 - 0 (src1 >= 0 ? 0 : -1) */ - code = arm_code_mm (COND_AL, MM_MODE_S, src1, dest, opcodes[type], zero); - ORC_ASM_CODE(p," %s %s, %s, %s\n", - codes[type], - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (zero)); - orc_arm_emit (p, code); + if (type == 0) + orc_arm_emit_ssub8 (p, ORC_ARM_COND_AL, dest, src1, zero); + else + orc_arm_emit_ssub16 (p, ORC_ARM_COND_AL, dest, src1, zero); - code = arm_code_mm (COND_AL, 0x68, zero, dest, 0xb, ones); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (zero), - orc_arm_reg_name (ones)); - orc_arm_emit (p, code); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, zero, ones); - /* src1 = 0 - src1 (src1 <= 0 ? 0 : -1) */ - code = arm_code_mm (COND_AL, MM_MODE_S, zero, tmp, opcodes[type], src1); - ORC_ASM_CODE(p," %s %s, %s, %s\n", - codes[type], - orc_arm_reg_name (tmp), - orc_arm_reg_name (zero), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + /* tmp = 0 - src1 (src1 <= 0 ? 0 : -1) */ + if (type == 0) + orc_arm_emit_ssub8 (p, ORC_ARM_COND_AL, tmp, zero, src1); + else + orc_arm_emit_ssub16 (p, ORC_ARM_COND_AL, tmp, zero, src1); - code = arm_code_mm (COND_AL, 0x68, zero, tmp, 0xb, ones); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (tmp), - orc_arm_reg_name (zero), - orc_arm_reg_name (ones)); - orc_arm_emit (p, code); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, tmp, zero, ones); /* (src1 >= 0 ? 0 : -1) - (src1 <= 0 ? 0 : -1) */ - code = arm_code_mm (COND_AL, MM_MODE_S, dest, dest, opcodes[type], tmp); - ORC_ASM_CODE(p," %s %s, %s, %s\n", - codes[type], - orc_arm_reg_name (dest), - orc_arm_reg_name (dest), - orc_arm_reg_name (tmp)); - orc_arm_emit (p, code); + if (type == 0) + orc_arm_emit_ssub8 (p, ORC_ARM_COND_AL, dest, dest, tmp); + else + orc_arm_emit_ssub16 (p, ORC_ARM_COND_AL, dest, dest, tmp); } -BINARY_MM (subb, "ssub8", MM_OP_SUB8, MM_MODE_S); -BINARY_MM (subssb, "qsub8", MM_OP_SUB8, MM_MODE_Q); -BINARY_MM (subusb, "uqsub8", MM_OP_SUB8, MM_MODE_UQ); -BINARY_DP (xorX, "eor", DP_EOR); - -BINARY_MM (addw, "sadd16", MM_OP_ADD16, MM_MODE_S); -BINARY_MM (addssw, "qadd16", MM_OP_ADD16, MM_MODE_Q); -BINARY_MM (addusw, "uqadd16", MM_OP_ADD16, MM_MODE_UQ); + +BINARY_MM (subb, ssub8); +BINARY_MM (subssb, qsub8); +BINARY_MM (subusb, uqsub8); +BINARY_DP (xorX, eor); + +BINARY_MM (addw, sadd16); +BINARY_MM (addssw, qadd16); +BINARY_MM (addusw, uqadd16); + static void arm_rule_maxsw (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_code_mm (COND_AL, MM_MODE_S, src1, dest, MM_OP_SUB16, src2); - ORC_ASM_CODE(p," ssub16 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_code_mm (COND_AL, 0x68, src1, dest, 0xb, src2); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + orc_arm_emit_ssub16 (p, ORC_ARM_COND_AL, dest, src1, src2); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src1, src2); } static void arm_rule_maxuw (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_code_mm (COND_AL, MM_MODE_U, src1, dest, MM_OP_SUB16, src2); - ORC_ASM_CODE(p," usub16 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_code_mm (COND_AL, 0x68, src1, dest, 0xb, src2); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + orc_arm_emit_usub16 (p, ORC_ARM_COND_AL, dest, src1, src2); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src1, src2); } static void arm_rule_minsw (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_code_mm (COND_AL, MM_MODE_S, src1, dest, MM_OP_SUB16, src2); - ORC_ASM_CODE(p," ssub16 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_code_mm (COND_AL, 0x68, src2, dest, 0xb, src1); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_ssub16 (p, ORC_ARM_COND_AL, dest, src1, src2); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src2, src1); } static void arm_rule_minuw (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_code_mm (COND_AL, MM_MODE_U, src1, dest, MM_OP_SUB16, src2); - ORC_ASM_CODE(p," usub16 %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_code_mm (COND_AL, 0x68, src2, dest, 0xb, src1); - ORC_ASM_CODE(p," sel %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_usub16 (p, ORC_ARM_COND_AL, dest, src1, src2); + orc_arm_emit_sel (p, ORC_ARM_COND_AL, dest, src2, src1); } static void @@ -811,238 +636,142 @@ arm_rule_mullw (OrcCompiler *p, void *user, OrcInstruction *insn) BINARY_SW(mulhsw, "(%s * %s) >> 16") BINARY_UW(mulhuw, "((uint32_t)((uint16_t)%s) * (uint32_t)((uint16_t)%s)) >> 16") #endif -BINARY_MM (subw, "ssub16", MM_OP_SUB16, MM_MODE_S); -BINARY_MM (subssw, "qsub16", MM_OP_SUB16, MM_MODE_Q); -BINARY_MM (subusw, "uqsub16", MM_OP_SUB16, MM_MODE_UQ); +BINARY_MM (subw, ssub16); +BINARY_MM (subssw, qsub16); +BINARY_MM (subusw, uqsub16); static void arm_rule_absl (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); /* reverse sign 0 - src1, assume the value is negative */ - code = arm_dp_imm (COND_AL, DP_RSB, 1, src1, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," rsbs %s, %s, #0\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_rsb_i (p, ORC_ARM_COND_AL, 1, dest, src1, 0, 0); /* if we got negative, copy the original value again */ - code = arm_dp_reg (COND_PL, DP_MOV, 0, 0, dest, arm_so_reg (src1)); - ORC_ASM_CODE(p," movmi %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_mov_r (p, ORC_ARM_COND_MI, 0, dest, src1); } -BINARY_DP (addl, "add", DP_ADD); -BINARY_MM (addssl, "qadd", 0x5, 0x10); +BINARY_DP (addl, add); +BINARY_MM (addssl, qadd); static void arm_rule_addusl (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_dp_reg (COND_AL, DP_ADD, 1, src1, dest, arm_so_reg (src2)); - ORC_ASM_CODE(p," adds %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + /* add numbers */ + orc_arm_emit_add_r (p, ORC_ARM_COND_AL, 1, dest, src1, src2); - code = arm_dp_imm (COND_CS, DP_MVN, 0, 0, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mvncs %s, #0\n", - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* on overflow, move ffffffff */ + orc_arm_emit_mvn_i (p, ORC_ARM_COND_CS, 0, dest, 0, 0); } static void arm_rule_avgXl (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); /* set the carry flag */ - code = arm_dp_reg (COND_AL, DP_SUB, 1, src1, dest, arm_so_reg (src1)); - ORC_ASM_CODE(p," subs %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src1); /* src1 + src2 + 1 */ - code = arm_dp_reg (COND_AL, DP_ADC, 0, src1, dest, arm_so_reg (src2)); - ORC_ASM_CODE(p," adc %s, %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + orc_arm_emit_adc_r (p, ORC_ARM_COND_AL, 0, dest, src1, src2); /* rotate right, top bit is the carry */ - code = arm_dp_reg (COND_AL, DP_MOV, 0, 0, dest, arm_so_rrx_reg (dest)); - ORC_ASM_CODE(p," mov %s, %s, RRX\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); - + orc_arm_emit_mov_rrx (p, ORC_ARM_COND_AL, 0, dest, dest); } static void arm_rule_cmpeql (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_dp_reg (COND_AL, DP_CMP, 1, src1, 0, arm_so_reg (src2)); - ORC_ASM_CODE(p," cmp %s, %s\n", - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + /* compare */ + orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src2); - code = arm_dp_imm (COND_NE, DP_MOV, 0, 0, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," movne %s, #0\n", - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* set to all 0 when not equal */ + orc_arm_emit_mov_i (p, ORC_ARM_COND_NE, 0, dest, 0, 0); - code = arm_dp_imm (COND_EQ, DP_MVN, 0, 0, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mvneq %s, #0\n", - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* set to all ff when equal */ + orc_arm_emit_mvn_i (p, ORC_ARM_COND_EQ, 0, dest, 0, 0); } static void arm_rule_cmpgtsl (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_dp_reg (COND_AL, DP_CMP, 1, src1, 0, arm_so_reg (src2)); - ORC_ASM_CODE(p," cmp %s, %s\n", - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + /* compare */ + orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src2); - code = arm_dp_imm (COND_LE, DP_MOV, 0, 0, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," movle %s, #0\n", - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* set to all 0 when less or equal */ + orc_arm_emit_mov_i (p, ORC_ARM_COND_LE, 0, dest, 0, 0); - code = arm_dp_imm (COND_GT, DP_MVN, 0, 0, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," mvngt %s, #0\n", - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* set to all ff when greater */ + orc_arm_emit_mvn_i (p, ORC_ARM_COND_GT, 0, dest, 0, 0); } static void arm_rule_maxsl (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_dp_reg (COND_AL, DP_CMP, 1, src1, 0, arm_so_reg (src2)); - ORC_ASM_CODE(p," cmp %s, %s\n", - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_dp_reg (COND_GE, DP_MOV, 0, 0, dest, arm_so_reg (src1)); - ORC_ASM_CODE(p," movge %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + /* compare */ + orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src2); - code = arm_dp_reg (COND_LT, DP_MOV, 0, 0, dest, arm_so_reg (src2)); - ORC_ASM_CODE(p," movlt %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + /* conditionally move result */ + orc_arm_emit_mov_r (p, ORC_ARM_COND_GE, 0, dest, src1); + orc_arm_emit_mov_r (p, ORC_ARM_COND_LT, 0, dest, src2); } static void arm_rule_maxul (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_dp_reg (COND_AL, DP_CMP, 1, src1, 0, arm_so_reg (src2)); - ORC_ASM_CODE(p," cmp %s, %s\n", - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_dp_reg (COND_CS, DP_MOV, 0, 0, dest, arm_so_reg (src1)); - ORC_ASM_CODE(p," movcs %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + /* compare */ + orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src2); - code = arm_dp_reg (COND_CC, DP_MOV, 0, 0, dest, arm_so_reg (src2)); - ORC_ASM_CODE(p," movcc %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + /* conditionally move result */ + orc_arm_emit_mov_r (p, ORC_ARM_COND_CS, 0, dest, src1); + orc_arm_emit_mov_r (p, ORC_ARM_COND_CC, 0, dest, src2); } static void arm_rule_minsl (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_dp_reg (COND_AL, DP_CMP, 1, src1, 0, arm_so_reg (src2)); - ORC_ASM_CODE(p," cmp %s, %s\n", - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_dp_reg (COND_GE, DP_MOV, 0, 0, dest, arm_so_reg (src2)); - ORC_ASM_CODE(p," movge %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + /* compare */ + orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src2); - code = arm_dp_reg (COND_LT, DP_MOV, 0, 0, dest, arm_so_reg (src1)); - ORC_ASM_CODE(p," movlt %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + /* conditionally move result */ + orc_arm_emit_mov_r (p, ORC_ARM_COND_GE, 0, dest, src2); + orc_arm_emit_mov_r (p, ORC_ARM_COND_LT, 0, dest, src1); } static void arm_rule_minul (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int src2 = ORC_SRC_ARG (p, insn, 1); int dest = ORC_DEST_ARG (p, insn, 0); - code = arm_dp_reg (COND_AL, DP_CMP, 1, src1, 0, arm_so_reg (src2)); - ORC_ASM_CODE(p," cmp %s, %s\n", - orc_arm_reg_name (src1), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); - - code = arm_dp_reg (COND_CS, DP_MOV, 0, 0, dest, arm_so_reg (src2)); - ORC_ASM_CODE(p," movcs %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src2)); - orc_arm_emit (p, code); + /* compare */ + orc_arm_emit_cmp_r (p, ORC_ARM_COND_AL, src1, src2); - code = arm_dp_reg (COND_CC, DP_MOV, 0, 0, dest, arm_so_reg (src1)); - ORC_ASM_CODE(p," movcc %s, %s\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + /* conditionally move result */ + orc_arm_emit_mov_r (p, ORC_ARM_COND_CS, 0, dest, src2); + orc_arm_emit_mov_r (p, ORC_ARM_COND_CC, 0, dest, src1); } #if 0 @@ -1053,32 +782,21 @@ BINARY_UL(mulhul, "((uint64_t)%s * (uint64_t)%s) >> 32") static void arm_rule_signl (OrcCompiler *p, void *user, OrcInstruction *insn) { - uint32_t code; int src1 = ORC_SRC_ARG (p, insn, 0); int dest = ORC_DEST_ARG (p, insn, 0); int tmp = p->tmpreg; - code = arm_dp_imm (COND_AL, DP_RSB, 0, src1, dest, arm_so_imm (0,0)); - ORC_ASM_CODE(p," rsb %s, %s, #0\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + /* dest = 0 - src1 */ + orc_arm_emit_rsb_i (p, ORC_ARM_COND_AL, 0, dest, src1, 0, 0); - code = arm_dp_reg (COND_AL, DP_MOV, 0, 0, tmp, arm_so_shift_imm (31,SHIFT_ASR,src1)); - ORC_ASM_CODE(p," mov %s, %s, ASR #31\n", - orc_arm_reg_name (tmp), - orc_arm_reg_name (src1)); - orc_arm_emit (p, code); + /* move src1 sign into tmp */ + orc_arm_emit_mov_rsi (p, ORC_ARM_COND_AL, 0, tmp, src1, ORC_ARM_ASR, 31); - code = arm_dp_reg (COND_AL, DP_ADD, 0, tmp, dest, arm_so_shift_imm (31,SHIFT_ASR,dest)); - ORC_ASM_CODE(p," sub %s, %s, %s, ASR #31\n", - orc_arm_reg_name (dest), - orc_arm_reg_name (tmp), - orc_arm_reg_name (dest)); - orc_arm_emit (p, code); + /* dest = tmp - (dest >> 31) */ + orc_arm_emit_sub_rsi (p, ORC_ARM_COND_AL, 0, dest, tmp, dest, ORC_ARM_ASR, 31); } -BINARY_DP (subl, "sub", DP_SUB); -BINARY_MM (subssl, "qsub", 0x5, 0x12); +BINARY_DP (subl, sub); +BINARY_MM (subssl, qsub); #if 0 BINARY_UL(subusl, "ORC_CLAMP_UL((int64_t)(uint32_t)%s - (int64_t)(uint32_t)%s)") @@ -1127,17 +845,17 @@ orc_compiler_orc_arm_register_rules (OrcTarget *target) orc_rule_register (rule_set, "andnb", arm_rule_andnX, NULL); orc_rule_register (rule_set, "avgsb", arm_rule_avgX, (void *)3); orc_rule_register (rule_set, "avgub", arm_rule_avgX, (void *)0); - orc_rule_register (rule_set, "cmpeqb", arm_rule_cmpeqX, (void *)0); - orc_rule_register (rule_set, "cmpgtsb", arm_rule_cmpgtsX, (void *)0); + orc_rule_register (rule_set, "cmpeqb", arm_rule_cmpeqX, (void *)1); + orc_rule_register (rule_set, "cmpgtsb", arm_rule_cmpgtsX, (void *)1); orc_rule_register (rule_set, "copyb", arm_rule_copyX, NULL); orc_rule_register (rule_set, "maxsb", arm_rule_maxsb, NULL); orc_rule_register (rule_set, "maxub", arm_rule_maxub, NULL); orc_rule_register (rule_set, "minsb", arm_rule_minsb, NULL); orc_rule_register (rule_set, "minub", arm_rule_minub, NULL); orc_rule_register (rule_set, "orb", arm_rule_orX, NULL); - orc_rule_register (rule_set, "shlb", arm_rule_shift, (void *)0); - orc_rule_register (rule_set, "shrsb", arm_rule_shift, (void *)1); - orc_rule_register (rule_set, "shrub", arm_rule_shift, (void *)2); + orc_rule_register (rule_set, "shlb", arm_rule_shlX, (void *)1); + orc_rule_register (rule_set, "shrsb", arm_rule_shrsX, (void *)1); + orc_rule_register (rule_set, "shrub", arm_rule_shruX, (void *)1); orc_rule_register (rule_set, "signb", arm_rule_signX, (void *)0); orc_rule_register (rule_set, "subb", arm_rule_subb, NULL); orc_rule_register (rule_set, "subssb", arm_rule_subssb, NULL); @@ -1152,17 +870,17 @@ orc_compiler_orc_arm_register_rules (OrcTarget *target) orc_rule_register (rule_set, "andnw", arm_rule_andnX, NULL); orc_rule_register (rule_set, "avgsw", arm_rule_avgX, (void *)2); orc_rule_register (rule_set, "avguw", arm_rule_avgX, (void *)1); - orc_rule_register (rule_set, "cmpeqw", arm_rule_cmpeqX, (void *)1); - orc_rule_register (rule_set, "cmpgtsw", arm_rule_cmpgtsX, (void *)1); + orc_rule_register (rule_set, "cmpeqw", arm_rule_cmpeqX, (void *)2); + orc_rule_register (rule_set, "cmpgtsw", arm_rule_cmpgtsX, (void *)2); orc_rule_register (rule_set, "copyw", arm_rule_copyX, NULL); orc_rule_register (rule_set, "maxsw", arm_rule_maxsw, NULL); orc_rule_register (rule_set, "maxuw", arm_rule_maxuw, NULL); orc_rule_register (rule_set, "minsw", arm_rule_minsw, NULL); orc_rule_register (rule_set, "minuw", arm_rule_minuw, NULL); orc_rule_register (rule_set, "orw", arm_rule_orX, NULL); - orc_rule_register (rule_set, "shlw", arm_rule_shift, (void *)4); - orc_rule_register (rule_set, "shrsw", arm_rule_shift, (void *)5); - orc_rule_register (rule_set, "shruw", arm_rule_shift, (void *)6); + orc_rule_register (rule_set, "shlw", arm_rule_shlX, (void *)2); + orc_rule_register (rule_set, "shrsw", arm_rule_shrsX, (void *)2); + orc_rule_register (rule_set, "shruw", arm_rule_shruX, (void *)2); orc_rule_register (rule_set, "signw", arm_rule_signX, (void *)1); orc_rule_register (rule_set, "subw", arm_rule_subw, NULL); orc_rule_register (rule_set, "subssw", arm_rule_subssw, NULL); @@ -1186,9 +904,9 @@ orc_compiler_orc_arm_register_rules (OrcTarget *target) orc_rule_register (rule_set, "minsl", arm_rule_minsl, NULL); orc_rule_register (rule_set, "minul", arm_rule_minul, NULL); orc_rule_register (rule_set, "orl", arm_rule_orX, NULL); - orc_rule_register (rule_set, "shll", arm_rule_shift, (void *)8); - orc_rule_register (rule_set, "shrsl", arm_rule_shift, (void *)9); - orc_rule_register (rule_set, "shrul", arm_rule_shift, (void *)10); + orc_rule_register (rule_set, "shll", arm_rule_shlX, (void *)4); + orc_rule_register (rule_set, "shrsl", arm_rule_shrsX, (void *)4); + orc_rule_register (rule_set, "shrul", arm_rule_shruX, (void *)4); orc_rule_register (rule_set, "signl", arm_rule_signl, NULL); orc_rule_register (rule_set, "subl", arm_rule_subl, NULL); orc_rule_register (rule_set, "subssl", arm_rule_subssl, NULL); -- 2.7.4