From f28b13d75052732f6fc377cb4eb7b3fe3c5f60bc Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Mon, 23 Jun 2008 13:34:36 +0000 Subject: [PATCH] - add support for Rotl - fixed RRX comment - fixed constraints for ARM shift operations [r20220] --- ir/be/arm/arm_nodes_attr.h | 2 +- ir/be/arm/arm_spec.pl | 21 +++++------ ir/be/arm/arm_transform.c | 75 +++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 14 deletions(-) diff --git a/ir/be/arm/arm_nodes_attr.h b/ir/be/arm/arm_nodes_attr.h index 599011370..70d611b6d 100644 --- a/ir/be/arm/arm_nodes_attr.h +++ b/ir/be/arm/arm_nodes_attr.h @@ -40,7 +40,7 @@ typedef enum _arm_shift_modifier { ARM_SHF_LSL = 3, /**< logical shift left */ ARM_SHF_LSR = 4, /**< logical shift right */ ARM_SHF_ROR = 5, /**< rotate right */ - ARM_SHF_RRX = 6, /**< rotate with sign extend */ + ARM_SHF_RRX = 6, /**< rotate right through carry bits */ } arm_shift_modifier; /** True, if the modifier implies a shift argument */ diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index 3881351a9..5c9fe4e3c 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -445,25 +445,24 @@ Shl => { Shr => { irn_flags => "R", - comment => "construct Shr: Shr(a, b) = a >> b", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, + comment => "construct Shr: Shr(a, b) = a >>u b", + reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, emit => '. mov %D0, %S0, lsr %S1' }, Shrs => { irn_flags => "R", - comment => "construct Shrs: Shrs(a, b) = a >> b", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, + comment => "construct Shrs: Shrs(a, b) = a >>s b", + reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, emit => '. mov %D0, %S0, asr %S1' }, -#RotR => { -# irn_flags => "R", -# comment => "construct RotR: RotR(a, b) = a ROTR b", -# reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, -# emit => '. mov %D0, %S0, ror %S1 /* RotR(%S0, %S1) -> %D0, (%A1, %A2) */' -## emit => '. ror %S0, %S1, %D0' -#}, +Ror => { + irn_flags => "R", + comment => "construct Ror: Ror(a, b) = a <> b", + reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, + emit => '. mov %D0, %S0, ror %S1' +}, #RotL => { # irn_flags => "R", diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index 8f4f5919b..72f19982d 100644 --- a/ir/be/arm/arm_transform.c +++ b/ir/be/arm/arm_transform.c @@ -620,6 +620,78 @@ static ir_node *gen_Shrs(ir_node *node) { return new_rd_arm_Shrs(dbg, current_ir_graph, block, new_op1, new_op2, mode); } +/** + * Creates an ARM Ror. + * + * @return the created ARM Ror node + */ +static ir_node *gen_Ror(ir_node *node, ir_node *op1, ir_node *op2) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op1 = be_transform_node(op1); + ir_node *new_op2 = be_transform_node(op2); + ir_mode *mode = mode_Iu; + dbg_info *dbg = get_irn_dbg_info(node); + + if (is_arm_Mov_i(new_op2)) { + return new_rd_arm_Mov(dbg, current_ir_graph, block, new_op1, mode, ARM_SHF_ROR, get_arm_imm_value(new_op2)); + } + return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode); +} + +/** + * Creates an ARM Rol. + * + * @return the created ARM Rol node + * + * Note: there is no Rol on arm, we have to use Ror + */ +static ir_node *gen_Rol(ir_node *node, ir_node *op1, ir_node *op2) { + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_node *new_op1 = be_transform_node(op1); + ir_mode *mode = mode_Iu; + dbg_info *dbg = get_irn_dbg_info(node); + ir_node *new_op2 = new_rd_arm_Rsb_i(dbg, current_ir_graph, block, op2, mode, 32); + return new_rd_arm_Ror(dbg, current_ir_graph, block, new_op1, new_op2, mode); +} + +/** + * Creates an ARM ROR from a Firm Rotl. + * + * @return the created ARM Ror node + */ +static ir_node *gen_Rotl(ir_node *node) { + ir_node *rotate = NULL; + ir_node *op1 = get_Rotl_left(node); + ir_node *op2 = get_Rotl_right(node); + + /* Firm has only RotL, so we are looking for a right (op2) + operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e", + that means we can create a RotR. */ + + if (is_Add(op2)) { + ir_node *add = op2; + ir_node *left = get_Add_left(add); + ir_node *right = get_Add_right(add); + if (is_Const(right)) { + tarval *tv = get_Const_tarval(right); + ir_mode *mode = get_irn_mode(node); + long bits = get_mode_size_bits(mode); + + if (is_Minus(left) && + tarval_is_long(tv) && + get_tarval_long(tv) == bits && + bits == 32) + rotate = gen_Ror(node, op1, get_Minus_op(left)); + } + } + + if (rotate == NULL) { + rotate = gen_Rol(node, op1, op2); + } + + return rotate; +} + /** * Transforms a Not node. * @@ -1397,7 +1469,6 @@ static ir_node *gen_Proj(ir_node *node) { /* we exchange the ProjX with a jump */ block = be_transform_node(block); jump = new_rd_Jmp(dbgi, irg, block); - ir_fprintf(stderr, "created jump: %+F\n", jump); return jump; } if (node == get_irg_anchor(irg, anchor_tls)) { @@ -1549,7 +1620,7 @@ static void arm_register_transformers(void) { GEN(Shl); GEN(Shr); GEN(Shrs); - BAD(Rotl); /* unsupported yet */ + GEN(Rotl); GEN(Quot); -- 2.20.1