aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2012-02-02 19:51:42 +0200
committerPekka Enberg <penberg@kernel.org>2012-02-02 19:53:18 +0200
commit1ec17799a1e5d685682a12857beacca4a5f09fdd (patch)
tree09905dce3159013d7554db9de78ea8a7ed45aac6
parente02213005e1410f1e7115a504d229bc0e346a079 (diff)
downloadjato-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.c2
-rw-r--r--arch/arm/include/arch/instruction.h2
-rw-r--r--arch/arm/insn-selector.brg23
-rw-r--r--arch/arm/instruction.c2
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,
};