summaryrefslogtreecommitdiffhomepage
path: root/ir/lower
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2018-04-08 10:38:49 +0200
committerChristoph Mallon <christoph.mallon@gmx.de>2018-04-08 11:34:57 +0200
commitbb07fd0ff959958c5feef24d37c3abff69115945 (patch)
tree37e9b6fc6ef59eba0a9cf324dd1f15a4fe0f3d39 /ir/lower
parent8cf5a52f4d406b5f852dc2d1ab16f8abae1f921e (diff)
lower: Handle creation of the libgcc entities directly in the double word lowerer.
Before each backend specified the same names (or a subset thereof) by itself. Now also backends without explicit handling for several double word operations just use the libgcc functions. This re-uses the implementation of the SPARC backend, because it handled a superset of all others. Additionally the arm backend did not mangle the name. This was not critical because typical arm systems have no mangling.
Diffstat (limited to 'ir/lower')
-rw-r--r--ir/lower/lower_dw.c42
-rw-r--r--ir/lower/lower_dw.h22
2 files changed, 44 insertions, 20 deletions
diff --git a/ir/lower/lower_dw.c b/ir/lower/lower_dw.c
index 9494956..996a60f 100644
--- a/ir/lower/lower_dw.c
+++ b/ir/lower/lower_dw.c
@@ -452,6 +452,46 @@ static void lower_Store(ir_node *node, ir_mode *mode)
}
}
+static ir_entity *create_libgcc_entity(ir_type *const method, ir_op const *const op, ir_mode const *const imode, ir_mode const *const omode)
+{
+ const char *name;
+ if (op == op_Mul) {
+ name = "__muldi3";
+ } else if (op == op_Div) {
+ name = mode_is_signed(imode) ? "__divdi3" : "__udivdi3";
+ } else if (op == op_Mod) {
+ name = mode_is_signed(imode) ? "__moddi3" : "__umoddi3";
+ } else if (op == op_Conv) {
+ if (mode_is_float(imode)) {
+ assert(get_mode_size_bits(omode) == 64);
+ if (get_mode_size_bits(imode) == 64) {
+ name = mode_is_signed(omode) ? "__fixdfdi" : "__fixunsdfdi";
+ } else if (get_mode_size_bits(imode) == 32) {
+ name = mode_is_signed(omode) ? "__fixsfdi" : "__fixunssfdi";
+ } else {
+ assert(get_mode_size_bits(imode) == 128);
+ panic("can't conver long double to long long yet");
+ }
+ } else if (mode_is_float(omode)) {
+ assert(get_mode_size_bits(imode) == 64);
+ if (get_mode_size_bits(omode) == 64) {
+ name = mode_is_signed(imode) ? "__floatdidf" : "__floatundidf";
+ } else if (get_mode_size_bits(omode) == 32) {
+ name = mode_is_signed(imode) ? "__floatdisf" : "__floatundisf";
+ } else {
+ assert(get_mode_size_bits(omode) == 128);
+ panic("can't convert long long to long double yet");
+ }
+ } else {
+ panic("can't lower 64bit Conv");
+ }
+ } else {
+ panic("cannot lower unexpected 64bit operation %s", get_op_name(op));
+ }
+
+ return create_compilerlib_entity(name, method);
+}
+
/**
* Return a node containing the address of the intrinsic emulation function.
*
@@ -476,7 +516,7 @@ static ir_node *get_intrinsic_address(ir_type *method, ir_op *op,
ir_entity *ent = entry->ent;
if (ent == NULL) {
/* create a new one */
- ent = env.p.create_intrinsic(method, op, imode, omode, env.p.ctx);
+ ent = create_libgcc_entity(method, op, imode, omode);
assert(ent && "Intrinsic creator must return an entity");
entry->ent = ent;
diff --git a/ir/lower/lower_dw.h b/ir/lower/lower_dw.h
index a8a7680..8851b5b 100644
--- a/ir/lower/lower_dw.h
+++ b/ir/lower/lower_dw.h
@@ -22,29 +22,13 @@ typedef struct lower64_entry_t {
ir_node *high_word; /**< the high word */
} lower64_entry_t;
-
-/**
- * A callback type for creating an intrinsic entity for a given opcode.
- *
- * @param method the method type of the emulation function entity
- * @param op the emulated ir_op
- * @param imode the input mode of the emulated opcode
- * @param omode the output mode of the emulated opcode
- * @param context the context parameter
- */
-typedef ir_entity *(create_intrinsic_fkt)(ir_type *method, const ir_op *op,
- const ir_mode *imode,
- const ir_mode *omode, void *context);
-
/**
* The lowering parameter description.
*/
typedef struct lwrdw_param_t {
- create_intrinsic_fkt *create_intrinsic; /**< callback that creates the intrinsic entity */
- void *ctx; /**< context parameter for the creator function */
- ir_mode *word_unsigned; /**< mode for unsigned word */
- ir_mode *word_signed; /**< mode for signed word */
- unsigned short doubleword_size; /**< bitsize of the doubleword mode */
+ ir_mode *word_unsigned; /**< mode for unsigned word */
+ ir_mode *word_signed; /**< mode for signed word */
+ unsigned short doubleword_size; /**< bitsize of the doubleword mode */
} lwrdw_param_t;
/**