Commit 4fa8da0e authored by Matthias Braun's avatar Matthias Braun
Browse files

allow backend to specify endianess, rewrite bitfield emitter to handle little...

allow backend to specify endianess, rewrite bitfield emitter to handle little and big-endian byte order

[r27974]
parent 222011a8
......@@ -75,6 +75,8 @@ typedef struct backend_params {
unsigned support_inline_asm:1;
/** If set, the backend supports Rotl nodes */
unsigned support_rotl:1;
/** the backend uses big-endian byte ordering if set, else little endian */
unsigned byte_order_big_endian:1;
/** callback that performs lowerings required for target architecture */
lower_for_target_func lower_for_target;
......
......@@ -455,6 +455,7 @@ static const backend_params *TEMPLATE_get_backend_params(void)
static backend_params p = {
0, /* no inline assembly */
0, /* no support for Rotl nodes */
0, /* 0: little-endian, 1: big-endian */
TEMPLATE_lower_for_target, /* lowering for target */
NULL, /* architecture dependent settings, will be set later */
NULL, /* parameter for if conversion */
......
......@@ -612,6 +612,7 @@ static const backend_params *amd64_get_backend_params(void) {
static backend_params p = {
0, /* no inline assembly */
1, /* support Rotl nodes */
0, /* little endian */
amd64_lower_for_target, /* lowering callback */
NULL, /* will be set later */
NULL, /* parameter for if conversion */
......
......@@ -692,6 +692,7 @@ static const backend_params *arm_get_libfirm_params(void)
static backend_params p = {
0, /* don't support inline assembler yet */
1, /* support Rotl nodes */
1, /* big endian */
NULL, /* lowering function */
&ad, /* will be set later */
arm_is_mux_allowed, /* allow_ifconv function */
......
......@@ -1004,12 +1004,13 @@ static size_t max_vals;
static void emit_bitfield(normal_or_bitfield *vals, size_t offset_bits,
const ir_initializer_t *initializer, ir_type *type)
{
unsigned char last_bits = 0;
static const size_t BITS_PER_BYTE = 8;
ir_mode *mode = get_type_mode(type);
tarval *tv = NULL;
unsigned char curr_bits;
int value_len;
int j;
size_t bit_offset;
size_t end;
bool big_endian = be_get_backend_param()->byte_order_big_endian;
switch (get_initializer_kind(initializer)) {
case IR_INITIALIZER_NULL:
......@@ -1033,22 +1034,41 @@ static void emit_bitfield(normal_or_bitfield *vals, size_t offset_bits,
}
tv = tarval_convert_to(tv, get_type_mode(type));
/* normalize offset */
vals += offset_bits >> 3;
offset_bits &= 7;
value_len = get_mode_size_bits(mode);
/* combine bits with existing bits */
for (j = 0; value_len + (int) offset_bits > 0; ++j) {
assert((size_t) (vals - glob_vals) + j < max_vals);
assert(vals[j].kind == BITFIELD ||
(vals[j].kind == NORMAL && vals[j].v.value == NULL));
vals[j].kind = BITFIELD;
curr_bits = get_tarval_sub_bits(tv, j);
vals[j].v.bf_val
|= (last_bits >> (8 - offset_bits)) | (curr_bits << offset_bits);
value_len -= 8;
last_bits = curr_bits;
value_len = get_type_size_bytes(get_primitive_base_type(type));
bit_offset = 0;
end = get_mode_size_bits(mode);
while (bit_offset < end) {
size_t src_offset = bit_offset / BITS_PER_BYTE;
size_t src_offset_bits = bit_offset % BITS_PER_BYTE;
size_t dst_offset = (bit_offset+offset_bits) / BITS_PER_BYTE;
size_t dst_offset_bits = (bit_offset+offset_bits) % BITS_PER_BYTE;
size_t src_bits_len = end-bit_offset;
size_t dst_bits_len = BITS_PER_BYTE-dst_offset_bits;
unsigned char curr_bits;
normal_or_bitfield *val;
if (src_bits_len > dst_bits_len)
src_bits_len = dst_bits_len;
if (big_endian) {
val = &vals[value_len - dst_offset - 1];
} else {
val = &vals[dst_offset];
}
assert((val-glob_vals) < (ptrdiff_t) max_vals);
assert(val->kind == BITFIELD ||
(val->kind == NORMAL && val->v.value == NULL));
val->kind = BITFIELD;
curr_bits = get_tarval_sub_bits(tv, src_offset);
curr_bits = curr_bits >> src_offset_bits;
if (src_offset_bits + src_bits_len > 8) {
unsigned next_bits = get_tarval_sub_bits(tv, src_offset+1);
curr_bits |= next_bits << (8 - src_offset_bits);
}
curr_bits &= (1 << src_bits_len) - 1;
val->v.bf_val |= curr_bits << dst_offset_bits;
bit_offset += dst_bits_len;
}
}
......@@ -1125,11 +1145,12 @@ static void emit_ir_initializer(normal_or_bitfield *vals,
if (mode != NULL) {
size_t offset_bits
= get_entity_offset_bits_remainder(member);
size_t value_len = get_mode_size_bits(mode);
size_t value_len = get_mode_size_bits(mode);
if (offset_bits != 0 ||
(value_len != 8 && value_len != 16 && value_len != 32
&& value_len != 64)) {
&& value_len != 64) ||
(is_Primitive_type(subtype) && get_primitive_base_type(subtype) != NULL)) {
emit_bitfield(&vals[offset], offset_bits,
sub_initializer, subtype);
continue;
......
......@@ -340,20 +340,6 @@ int be_parse_arg(const char *arg)
return lc_opt_from_single_arg(be_grp, NULL, arg, NULL);
}
/** The be parameters returned by default, all off. */
static const backend_params be_params = {
0, /* don't support inline assembler yet */
0, /* don't support rotl */
NULL, /* no lowering required */
NULL, /* will be set later */
NULL, /* no if conversion settings */
NULL, /* no float arithmetic mode */
0, /* no trampoline support: size 0 */
0, /* no trampoline support: align 0 */
NULL, /* no trampoline support: no trampoline builder */
4 /* alignment of stack parameter */
};
/* Perform schedule verification if requested. */
static void be_sched_verify(ir_graph *irg, int verify_opt)
{
......@@ -380,9 +366,7 @@ void firm_be_finish(void)
/* Returns the backend parameter */
const backend_params *be_get_backend_param(void)
{
if (isa_if->get_params)
return isa_if->get_params();
return &be_params;
return isa_if->get_params();
}
/**
......
......@@ -2348,6 +2348,7 @@ static const backend_params *ia32_get_libfirm_params(void)
static backend_params p = {
1, /* support inline assembly */
1, /* support Rotl nodes */
0, /* little endian */
ia32_lower_for_target,
NULL, /* will be set later */
ia32_is_mux_allowed,
......
......@@ -572,6 +572,7 @@ static const backend_params *sparc_get_backend_params(void)
static backend_params p = {
0, /* no inline assembly */
0, /* no support for RotL nodes */
1, /* big endian */
sparc_lower_for_target, /* lowering callback */
&arch_dep, /* will be set later */
NULL, /* parameter for if conversion */
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment