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:
parent
28bf763373
commit
6ef3f7c13b
1 changed files with 57 additions and 16 deletions
|
|
@ -570,20 +570,54 @@ namespace
|
|||
|
||||
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
|
||||
{
|
||||
if(inst.type == instance_t::SINGLE)
|
||||
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)
|
||||
return inst.range.base;
|
||||
soc_word_t res;
|
||||
return inst.range.base; /* assume positive stride */
|
||||
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;
|
||||
for(size_t i = 0; i < inst.range.count; i++)
|
||||
{
|
||||
soc_word_t res;
|
||||
vars[inst.range.variable] = inst.range.first;
|
||||
error_context_t ctx;
|
||||
if(!evaluate_formula(inst.range.formula, vars, res, "", ctx))
|
||||
return 0xffffffff;
|
||||
return res;
|
||||
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 */
|
||||
|
|
@ -596,23 +630,30 @@ struct soc_sorter
|
|||
* any instance if instances are sorted) */
|
||||
bool operator()(const node_t& a, const node_t& b) const
|
||||
{
|
||||
/* borderline cases: no instances is lower than with instances */
|
||||
if(a.instance.size() == 0)
|
||||
return b.instance.size() > 0;
|
||||
if(b.instance.size() == 0)
|
||||
return false;
|
||||
return first_addr(a.instance[0]) < first_addr(b.instance[0]);
|
||||
soc_addr_t addr_a = first_addr(a);
|
||||
soc_addr_t addr_b = first_addr(b);
|
||||
/* It may happen that two nodes have the same first instance address,
|
||||
* for example if one logically splits a block into two blocks with
|
||||
* the same base. In this case, sort by name */
|
||||
if(addr_a == addr_b)
|
||||
return a.name < b.name;
|
||||
return addr_a < addr_b;
|
||||
}
|
||||
|
||||
/* sort fields by decreasing position */
|
||||
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;
|
||||
}
|
||||
|
||||
/* sort enum values by value */
|
||||
/* sort enum values by value, then by name */
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
|
@ -639,7 +680,7 @@ void normalize(node_t& node)
|
|||
std::sort(node.instance.begin(), node.instance.end(), soc_sorter());
|
||||
}
|
||||
|
||||
}
|
||||
} /* namespace */
|
||||
|
||||
void normalize(soc_t& soc)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue