简体   繁体   中英

Reading successive 3 bytes in a 32-bit word memory

I have a 32-bit word-addressable memory and my data section can start and end at any byte within the memory.

Lets suppose my data section starts at byte 2 (0 being Lowest byte) of word 0x3.

Then I have to read data from bytes 2 and 3 of word 0x3 and byte 0 of word 0x4. After this, I must read byte 1, 2 and 3 of word 0x4 and so on...And stop only when I all 3 bytes as zero OR my data section ends. The next section has extensible boundary and it can move into my data section so the ending word or byte is not fixed.

Do you have any suggestion on best possible algorithm to tackle this. I have come up with a way of creating two masks of total 24 bits which I move across words but that seems overkill and gives me large code. I'm trying to solve it in minimum possible C instructions. Looking forward to your advice.

from your statement it implies you can only read 32 bit words at a time, no 16 or 8 bit and that also implies you dont have to think/talk about alignment.

Just like the processors that do support byte addressable memory, you can implement it the same way if you have an address 0x1002 and you have some 24 bit item then

0x1002 = 0b0001000000000010 the lower two bits describe the byte in the word the upper bits the word number/address 0b00010000000000 0b10 so word address 0x400 starting with byte 2 (endianness is of course a factor, assuming little). you also know that 4 - 0b10 = 2 means there are two bytes left in this word and if you need a third you start at offset 0 in the next word.

so you could do something like this untested code:

unsigned int get24 ( unsigned int x )
{  
    unsigned int ra;
    unsigned int ret;
    unsigned int wa;
    unsigned int shift;
    unsigned int rb;

    ret=0;
    wa=x>>2;
    shift=(x&3)<<3;
    rb=load32(wa);
    for(ra=0;ra<3;ra++)
    {
       ret<<=8;
       ret|=(rb>>shift)&0xFF;
       shift+=8;
       if(shift>=32)
       {
           wa++;
           rb=load32(wa);
           shift=0;
       }
    }
}

you can take the byte based approach in another answer, but you have to make sure the compiler is aware of your word based memory limitations, it cant be allowed to do byte reads (well depends on the architecture), nor unaligned accesses (depends on the architecture).

You could try table based

//0x00000000 0x00FFFFFF
//0x00000000 0xFFFFFF00
//0x000000FF 0xFFFF0000
//0x0000FFFF 0xFF000000

unsigned int al[4]={0,0,24,16};
unsigned int ar[4]={0,0,8,8};
unsigned int bl[4]={8,0,16,24};
unsigned int br[4]={8,8,16,24};

unsigned int wa;
unsigned int off;
unsigned int ra;
unsigned int rb;
unsigned int ret;

wa=byte_address>>2;
off=byte_address&3;
rb=load32(wa);
ret=(rb<<bl[off])>>br[off];
//ret=(rb<<bl[off])>>(off<<3);
if(off&2)
{
    ra=load32(wa+1);
    //ret|=(ra<<al[off])>>ar[off];
    ret|=(ra<<al[off])>>8;
}

or jump table based

wa=byte_address>>2;
rb=load32(wa);
//if(byte_address&0xC)
ra=load32(wa+1);
switch(byte_address&3)
{
    case 0:
    {
        ret=(rb<<8)>>8;
        break;
    }
    case 1:
    {
        ret=rb>>8;
        break;
    }
    case 2:
    {
        ret=(rb<<16)>>16;
        ret|=(ra<<24)>>8;
        break;
    }
    case 3:
    {
        ret=(rb<<24)>>24;
        ret|=(ra<<16)>>8;
        break;
    }
}

I don't really understand what you mean by next section , extensible boundary and it can move . Ignoring that the below code should work for reading the data:

int start_word = 3;
int start_byte = 2;
int end_word = 100;
uint8_t* p = data + start_word * 4 + start_byte;
uint8_t* end = data + end_word * 100;

while (p + 3 <= end) { // 3 more bytes must be available
    uint8_t b0 = *p++;
    uint8_t b1 = *p++;
    uint8_t b2 = *p++;
    if (b0 == 0 && b1 == 0 && b2 == 0)
         break;
    // do something with the 3 bytes
}

The idea is not to care too much about words and work byte-wise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM