aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-22 18:21:24 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:06:16 -0700
commit741bbde940215dd3c9d9d4ea011af4e3764c4a31 (patch)
tree3c6c3422a6aa00547adadf1cbcf57ad0951694ac /linearize.c
parentMake linearizer able to handle assignment ops where the (diff)
downloadsparse-741bbde940215dd3c9d9d4ea011af4e3764c4a31.tar.gz
sparse-741bbde940215dd3c9d9d4ea011af4e3764c4a31.tar.bz2
sparse-741bbde940215dd3c9d9d4ea011af4e3764c4a31.zip
Split the binops where signedness matters into unsigned and signed.
This is OP_MUL/OP_DIV/OP_MOD/OP_SHR. We actually do the constant simplifications still wrong, but now the information is all there.
Diffstat (limited to 'linearize.c')
-rw-r--r--linearize.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/linearize.c b/linearize.c
index eccac80..98030c6 100644
--- a/linearize.c
+++ b/linearize.c
@@ -166,11 +166,15 @@ static const char* opcodes[] = {
/* Binary */
[OP_ADD] = "add",
[OP_SUB] = "sub",
- [OP_MUL] = "mul",
- [OP_DIV] = "div",
- [OP_MOD] = "mod",
+ [OP_MULU] = "mulu",
+ [OP_MULS] = "muls",
+ [OP_DIVU] = "divu",
+ [OP_DIVS] = "divs",
+ [OP_MODU] = "modu",
+ [OP_MODS] = "mods",
[OP_SHL] = "shl",
- [OP_SHR] = "shr",
+ [OP_LSR] = "lsr",
+ [OP_ASR] = "asr",
/* Logical */
[OP_AND] = "and",
@@ -962,7 +966,7 @@ static pseudo_t linearize_load_gen(struct entrypoint *ep, struct access_data *ad
if (ad->bit_offset) {
pseudo_t shift = value_pseudo(ad->bit_offset);
- pseudo_t newval = add_binary_op(ep, ad->source_type, OP_SHR, new, shift);
+ pseudo_t newval = add_binary_op(ep, ad->source_type, OP_LSR, new, shift);
new = newval;
}
@@ -1102,6 +1106,17 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol *
return result;
}
+static int opcode_sign(int opcode, struct symbol *ctype)
+{
+ if (ctype->ctype.modifiers & MOD_SIGNED) {
+ switch(opcode) {
+ case OP_MULU: case OP_DIVU: case OP_MODU: case OP_LSR:
+ opcode++;
+ }
+ }
+ return opcode;
+}
+
static pseudo_t linearize_assignment(struct entrypoint *ep, struct expression *expr)
{
struct access_data ad = { NULL, };
@@ -1118,17 +1133,20 @@ static pseudo_t linearize_assignment(struct entrypoint *ep, struct expression *e
static const int op_trans[] = {
[SPECIAL_ADD_ASSIGN - SPECIAL_BASE] = OP_ADD,
[SPECIAL_SUB_ASSIGN - SPECIAL_BASE] = OP_SUB,
- [SPECIAL_MUL_ASSIGN - SPECIAL_BASE] = OP_MUL,
- [SPECIAL_DIV_ASSIGN - SPECIAL_BASE] = OP_DIV,
- [SPECIAL_MOD_ASSIGN - SPECIAL_BASE] = OP_MOD,
+ [SPECIAL_MUL_ASSIGN - SPECIAL_BASE] = OP_MULU,
+ [SPECIAL_DIV_ASSIGN - SPECIAL_BASE] = OP_DIVU,
+ [SPECIAL_MOD_ASSIGN - SPECIAL_BASE] = OP_MODU,
[SPECIAL_SHL_ASSIGN - SPECIAL_BASE] = OP_SHL,
- [SPECIAL_SHR_ASSIGN - SPECIAL_BASE] = OP_SHR,
+ [SPECIAL_SHR_ASSIGN - SPECIAL_BASE] = OP_LSR,
[SPECIAL_AND_ASSIGN - SPECIAL_BASE] = OP_AND,
[SPECIAL_OR_ASSIGN - SPECIAL_BASE] = OP_OR,
[SPECIAL_XOR_ASSIGN - SPECIAL_BASE] = OP_XOR
};
+ int opcode;
+
oldvalue = cast_pseudo(ep, oldvalue, src->ctype, expr->ctype);
- dst = add_binary_op(ep, src->ctype, op_trans[expr->op - SPECIAL_BASE], oldvalue, value);
+ opcode = opcode_sign(op_trans[expr->op - SPECIAL_BASE], src->ctype);
+ dst = add_binary_op(ep, src->ctype, opcode, oldvalue, value);
value = cast_pseudo(ep, dst, expr->ctype, src->ctype);
}
value = linearize_store_gen(ep, value, &ad);
@@ -1197,18 +1215,20 @@ static pseudo_t linearize_binop(struct entrypoint *ep, struct expression *expr)
pseudo_t src1, src2, dst;
static const int opcode[] = {
['+'] = OP_ADD, ['-'] = OP_SUB,
- ['*'] = OP_MUL, ['/'] = OP_DIV,
- ['%'] = OP_MOD, ['&'] = OP_AND,
+ ['*'] = OP_MULU, ['/'] = OP_DIVU,
+ ['%'] = OP_MODU, ['&'] = OP_AND,
['|'] = OP_OR, ['^'] = OP_XOR,
[SPECIAL_LEFTSHIFT] = OP_SHL,
- [SPECIAL_RIGHTSHIFT] = OP_SHR,
+ [SPECIAL_RIGHTSHIFT] = OP_LSR,
[SPECIAL_LOGICAL_AND] = OP_AND_BOOL,
[SPECIAL_LOGICAL_OR] = OP_OR_BOOL,
};
+ int op;
src1 = linearize_expression(ep, expr->left);
src2 = linearize_expression(ep, expr->right);
- dst = add_binary_op(ep, expr->ctype, opcode[expr->op], src1, src2);
+ op = opcode_sign(opcode[expr->op], expr->ctype);
+ dst = add_binary_op(ep, expr->ctype, op, src1, src2);
return dst;
}