diff options
author | Pekka Enberg <penberg@kernel.org> | 2012-02-02 19:51:42 +0200 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2012-02-02 19:53:18 +0200 |
commit | 1ec17799a1e5d685682a12857beacca4a5f09fdd (patch) | |
tree | 09905dce3159013d7554db9de78ea8a7ed45aac6 | |
parent | e02213005e1410f1e7115a504d229bc0e346a079 (diff) | |
download | jato-1ec17799a1e5d685682a12857beacca4a5f09fdd.tar.gz |
arm: Fix 32-bit OP_ADD and OP_SUB instruction selection
Use 'add' and 'sub' instructions instead of 'adds' and 'subs' for 32-bit
operations, respectively.
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r-- | arch/arm/encode.c | 2 | ||||
-rw-r--r-- | arch/arm/include/arch/instruction.h | 2 | ||||
-rw-r--r-- | arch/arm/insn-selector.brg | 23 | ||||
-rw-r--r-- | arch/arm/instruction.c | 2 |
4 files changed, 22 insertions, 7 deletions
diff --git a/arch/arm/encode.c b/arch/arm/encode.c index f1cae1b3..86a48124 100644 --- a/arch/arm/encode.c +++ b/arch/arm/encode.c @@ -107,6 +107,7 @@ static uint32_t arm_encode_insn[] = { [INSN_ADC_REG_IMM] = AL | DATA_PROCESSING | USE_IMM_OPERAND | OPCODE(0x5), [INSN_ADC_REG_REG] = AL | DATA_PROCESSING | OPCODE(0x5), [INSN_ADDS_REG_IMM] = AL | DATA_PROCESSING | USE_IMM_OPERAND | S_BIT_HIGH | OPCODE(0x4), + [INSN_ADD_REG_REG] = AL | DATA_PROCESSING | OPCODE(0x4), [INSN_ADDS_REG_REG] = AL | DATA_PROCESSING | S_BIT_HIGH | OPCODE(0x4), [INSN_MOV_REG_IMM] = AL | DATA_PROCESSING | USE_IMM_OPERAND | OPCODE(0xD), [INSN_MOV_REG_REG] = AL | DATA_PROCESSING | OPCODE(0xD), @@ -118,6 +119,7 @@ static uint32_t arm_encode_insn[] = { [INSN_SBC_REG_IMM] = AL | DATA_PROCESSING | USE_IMM_OPERAND | OPCODE(0x6), [INSN_SBC_REG_REG] = AL | DATA_PROCESSING | OPCODE(0x6), [INSN_SUBS_REG_IMM] = AL | DATA_PROCESSING | USE_IMM_OPERAND | S_BIT_HIGH | OPCODE(0x2), + [INSN_SUB_REG_REG] = AL | DATA_PROCESSING | OPCODE(0x2), [INSN_SUBS_REG_REG] = AL | DATA_PROCESSING | S_BIT_HIGH | OPCODE(0x2), [INSN_UNCOND_BRANCH] = AL | BRANCH | USE_IMM_OPERAND, [INSN_PHI] = INVALID_INSN, diff --git a/arch/arm/include/arch/instruction.h b/arch/arm/include/arch/instruction.h index faaba9e4..3de2d326 100644 --- a/arch/arm/include/arch/instruction.h +++ b/arch/arm/include/arch/instruction.h @@ -80,6 +80,7 @@ static inline bool operand_is_reg(struct operand *operand) enum insn_type { INSN_ADD_REG_IMM, INSN_ADC_REG_IMM, + INSN_ADD_REG_REG, INSN_ADC_REG_REG, INSN_ADDS_REG_IMM, INSN_ADDS_REG_REG, @@ -99,6 +100,7 @@ enum insn_type { INSN_SBC_REG_IMM, INSN_SBC_REG_REG, INSN_SUBS_REG_IMM, + INSN_SUB_REG_REG, INSN_SUBS_REG_REG, INSN_UNCOND_BRANCH, /* Must be last */ diff --git a/arch/arm/insn-selector.brg b/arch/arm/insn-selector.brg index 66ab9fae..4449381b 100644 --- a/arch/arm/insn-selector.brg +++ b/arch/arm/insn-selector.brg @@ -121,14 +121,26 @@ reg: EXPR_LOCAL 1 reg: OP_ADD(reg, reg) 1 { - binop_reg_reg_low(state, s, tree, INSN_ADDS_REG_REG); - binop_reg_reg_high(state, s, tree, INSN_ADC_REG_REG); + struct expression *expr = to_expr(tree); + + if (expr->vm_type == J_LONG) { + binop_reg_reg_low(state, s, tree, INSN_ADDS_REG_REG); + binop_reg_reg_high(state, s, tree, INSN_ADC_REG_REG); + } else { + binop_reg_reg_low(state, s, tree, INSN_ADD_REG_REG); + } } reg: OP_SUB(reg, reg) 1 { - binop_reg_reg_low(state, s, tree, INSN_SUBS_REG_REG); - binop_reg_reg_high(state, s, tree, INSN_SBC_REG_REG); + struct expression *expr = to_expr(tree); + + if (expr->vm_type == J_LONG) { + binop_reg_reg_low(state, s, tree, INSN_SUBS_REG_REG); + binop_reg_reg_high(state, s, tree, INSN_SBC_REG_REG); + } else { + binop_reg_reg_low(state, s, tree, INSN_SUB_REG_REG); + } } stmt: STMT_EXPRESSION(reg) @@ -270,9 +282,6 @@ static void binop_reg_reg_high(struct _MBState *state, struct basic_block *bb, struct var_info *src, *dst; struct expression *expr = to_expr(tree); - if (expr->vm_type != J_LONG) - return; - src = state->right->reg2; dst = state->left->reg2; diff --git a/arch/arm/instruction.c b/arch/arm/instruction.c index 09bf53b0..27a41345 100644 --- a/arch/arm/instruction.c +++ b/arch/arm/instruction.c @@ -22,6 +22,7 @@ enum { static unsigned long insn_flags[] = { [INSN_ADC_REG_IMM] = USE_DST | DEF_DST, + [INSN_ADD_REG_REG] = USE_SRC | USE_DST | DEF_DST, [INSN_ADC_REG_REG] = USE_SRC | USE_DST | DEF_DST, [INSN_ADDS_REG_IMM] = USE_DST | DEF_DST, [INSN_ADDS_REG_REG] = USE_SRC | USE_DST | DEF_DST, @@ -34,6 +35,7 @@ static unsigned long insn_flags[] = { [INSN_SBC_REG_IMM] = USE_DST | DEF_DST, [INSN_SBC_REG_REG] = USE_SRC | USE_DST | DEF_DST, [INSN_SUBS_REG_IMM] = USE_DST | DEF_DST, + [INSN_SUB_REG_REG] = USE_SRC | USE_DST | DEF_DST, [INSN_SUBS_REG_REG] = USE_SRC | USE_DST | DEF_DST, [INSN_UNCOND_BRANCH] = USE_NONE | DEF_NONE | TYPE_BRANCH, }; |