[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Transputer - schools



Larry Dickson wrote:
Can you go into detail about these "literal pools"? I don't remember seeing such a thing (probably it had a different name). I remember the static chain, which sounded complicated.

What I'm wondering is whether they can be avoided or simplified by following a coding convention. Then, if the other cases were done inefficiently, it would not matter so much.

ARM processors - at least the architecture available then - were limited in where they could load or save, using a single instruction, to addresses IIRC +/- 4096 bytes of the PC. If you needed an address outside of that range, you had to calculate or load the address into a register. Similarly, any non-trivial constant had to be loaded in the same way. Therefore, in ARM code you find, between blocks of opcodes, these pools or blocks of literal values that are used by the code in the surrounding area. This is because ARM opcodes are always one 32-bit word, so you can't have a 32-bit constant in one of them.

The problem I had was that, without knowing more about the context than a single instruction, it was hard to translate transputer-code values and addresses into anything remotely efficient in ARM terms, so these literal pools became big - so big in some cases that it became impossible to use just pools at function boundaries. That was when I started looking around for alternatives.

Below I've included some of the code I wrote to work out whether a constant could be loaded directly or whether it had to be pooled.

Regards
Ruth


/* will v fit in mask m (eg. 0xff) with a shift of 2n? */

__inline unsigned int rotate_left_by_2(unsigned int v)
{
    unsigned r = (v << 2) | (v >> (30));
    return r;
}

unsigned int is_arm_immed(unsigned int v, int m)
{
    int n;
    int nm = ~m; /* e.g. 0xffffff00 */

    n = 0;
    while ((n < 14) && ((v & nm) == 0))
    {
        v = rotate_left_by_2(v);
        n++;
    }
    return (n != 14);
}

int big (int n, int bits)                     /* deal with big operands (12..32 bits) */
{
    if (bits == 8)
    {
        /* small means it will fit in 8 bits, modified by an even rotate, with sign independent */
        int k = (n >= 0) ? n : -n;
       
        if (is_arm_immed(k, 0xff))
        {
            mnem("ldimm"); T0; dec(n); COMMENT("big constant"); NL;
            return 1;
        }
    }
    else /* 12 bits excl. sign, straight */
    {
        if (is_arm_immed(n, 0xfff))
        {
            mnem("ldimm"); T0; dec(n); COMMENT("big constant"); NL;
            return 1;
        }
    }   
   
    return 0;
}




-- 
Software Manager & Engineer
Tel: 01223 414180
Blog: http://www.ivimey.org/blog
LinkedIn: http://uk.linkedin.com/in/ruthivimeycook/