1
0
Fork 0
forked from len0rd/rockbox

regtools: fix normalization procedure

The code was not updated when I added support for list and other stuff, and thus
it did not properly sort by addresses.

Change-Id: Iaed0717b607beedfb2856c020c2a760e7a5667c5
This commit is contained in:
Amaury Pouly 2017-01-23 16:07:41 +01:00
parent 28bf763373
commit 6ef3f7c13b

View file

@ -570,20 +570,54 @@ namespace
struct soc_sorter struct soc_sorter
{ {
/* returns the first (lowest) address of an instance */ /* returns the lowest address of an instance, or 0 if none
* and 0xffffffff if cannot evaluate */
soc_addr_t first_addr(const instance_t& inst) const soc_addr_t first_addr(const instance_t& inst) const
{ {
if(inst.type == instance_t::SINGLE) if(inst.type == instance_t::SINGLE)
return inst.addr; return inst.addr;
/* sanity check */
if(inst.type != instance_t::RANGE)
{
printf("Warning: unknown instance type %d\n", inst.type);
return 0;
}
if(inst.range.type == range_t::STRIDE) if(inst.range.type == range_t::STRIDE)
return inst.range.base; return inst.range.base; /* assume positive stride */
soc_word_t res; if(inst.range.type == range_t::LIST)
{
soc_addr_t min = 0xffffffff;
for(size_t i = 0; i < inst.range.list.size(); i++)
if(inst.range.list[i] < min)
min = inst.range.list[i];
return min;
}
/* sanity check */
if(inst.range.type != range_t::FORMULA)
{
printf("Warning: unknown range type %d\n", inst.range.type);
return 0;
}
soc_addr_t min = 0xffffffff;
std::map< std::string, soc_word_t > vars; std::map< std::string, soc_word_t > vars;
vars[inst.range.variable] = inst.range.first; for(size_t i = 0; i < inst.range.count; i++)
error_context_t ctx; {
if(!evaluate_formula(inst.range.formula, vars, res, "", ctx)) soc_word_t res;
return 0xffffffff; vars[inst.range.variable] = inst.range.first;
return res; error_context_t ctx;
if(evaluate_formula(inst.range.formula, vars, res, "", ctx) && res < min)
min = res;
}
return min;
}
/* return smallest address among all instances */
soc_addr_t first_addr(const node_t& node) const
{
soc_addr_t min = 0xffffffff;
for(size_t i = 0; i < node.instance.size(); i++)
min = std::min(min, first_addr(node.instance[i]));
return min;
} }
/* sort instances by first address */ /* sort instances by first address */
@ -596,23 +630,30 @@ struct soc_sorter
* any instance if instances are sorted) */ * any instance if instances are sorted) */
bool operator()(const node_t& a, const node_t& b) const bool operator()(const node_t& a, const node_t& b) const
{ {
/* borderline cases: no instances is lower than with instances */ soc_addr_t addr_a = first_addr(a);
if(a.instance.size() == 0) soc_addr_t addr_b = first_addr(b);
return b.instance.size() > 0; /* It may happen that two nodes have the same first instance address,
if(b.instance.size() == 0) * for example if one logically splits a block into two blocks with
return false; * the same base. In this case, sort by name */
return first_addr(a.instance[0]) < first_addr(b.instance[0]); if(addr_a == addr_b)
return a.name < b.name;
return addr_a < addr_b;
} }
/* sort fields by decreasing position */ /* sort fields by decreasing position */
bool operator()(const field_t& a, const field_t& b) const bool operator()(const field_t& a, const field_t& b) const
{ {
/* in the unlikely case where two fields have the same position, use name */
if(a.pos == b.pos)
return a.name < b.name;
return a.pos > b.pos; return a.pos > b.pos;
} }
/* sort enum values by value */ /* sort enum values by value, then by name */
bool operator()(const enum_t& a, const enum_t& b) const bool operator()(const enum_t& a, const enum_t& b) const
{ {
if(a.value == b.value)
return a.name < b.name;
return a.value < b.value; return a.value < b.value;
} }
}; };
@ -639,7 +680,7 @@ void normalize(node_t& node)
std::sort(node.instance.begin(), node.instance.end(), soc_sorter()); std::sort(node.instance.begin(), node.instance.end(), soc_sorter());
} }
} } /* namespace */
void normalize(soc_t& soc) void normalize(soc_t& soc)
{ {