How to mirror a byte

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 
7,122件の閲覧回数
pelle2005reg
Contributor I

Hi to all,

i would like to say if in the HCS12 assembler there is a instruction to mirror a byte.

That is, "convert" a byte in his mirror, for example:
$01 --> $80

$A1 --> $85

 

An istruction o a set of instruction (the fatest) .

Thank you

ラベル(1)
0 件の賞賛
返信
1 解決策
3,114件の閲覧回数
CompilerGuru
NXP Employee
NXP Employee

The fastest way is probably a table lookup if you can afford the memory for a 256 bytes table.

 

Daniel

元の投稿で解決策を見る

0 件の賞賛
返信
6 返答(返信)
3,115件の閲覧回数
CompilerGuru
NXP Employee
NXP Employee

The fastest way is probably a table lookup if you can afford the memory for a 256 bytes table.

 

Daniel

0 件の賞賛
返信
3,114件の閲覧回数
pelle2005reg
Contributor I
The table solution was also my first idea.
0 件の賞賛
返信
3,114件の閲覧回数
bigmac
Specialist III

Hello,

 

If my estimations are correct, the byte table lookup method should occupy about 7 cycles.  The nybble table lookup method would seem much less efficient at about 30 cycles (using assembly code, rather than C).  This would compare with the "shift loop" method at about 44 cycles.  I assumed that ACCB contained the byte value to be mirrored, and that the result was also in ACCB.

 

The byte table lookup code might consist of the following:

   ldx   #BYTETAB   ; Start of byte table

   abx

   ldab  0,x

 

Regards,

Mac

 

0 件の賞賛
返信
3,114件の閲覧回数
kef
Specialist I

Mac,

 

HC12 indexed addressing allows LDAB  B,X  , so -2 cycles saved on ABX.

Also loop unrolling should be considered. With single cycle shift instructions RORB, ROLA, or similar, reversing bits order from B to A should take 2cycles per bit, 2*8=16 cycles. + 1 cycle to transfer result back from A to B.

 

0 件の賞賛
返信
3,114件の閲覧回数
Lundin
Senior Contributor IV
This C code is fairly effective too. It works on nibble-level instead of byte-level, to save ROM:

#pragma CONST_SEG GLOBAL_ROM

static const uint8 MIRROR_TABLE[16] =
{
  0x0, 0x8, 0x4, 0xC,  /*  0-3  */
  0x2, 0xA, 0x6, 0xE,  /*  4-7  */
  0x1, 0x9, 0x5, 0xD,  /*  8-11 */
  0x3, 0xB, 0x7, 0xF   /* 12-15 */
};

#pragma CONST_SEG DEFAULT


uint8 my_byte; /* byte to mirror */
uint8 tmp;

tmp = MIRROR_TABLE[my_byte >> 4];
tmp <<= 4;
my_byte = MIRROR_TABLE[my_byte & 0x0F] | tmp;


On a Freescale micro, the left shift will be optimized into a MUL instruction, saving a few ticks. The right shift will become 4 LSRx instructions (no optimization possible).

If you expand the lookup table from 16 bytes to 256 bytes you don't need to do the shifting and thus save 10 CPU ticks or so, at the cost of ROM.
Message Edited by Lundin on 2009-12-01 11:46 AM
0 件の賞賛
返信
3,114件の閲覧回数
AndersJ
Contributor IV

The C code to mirror a byte may be fairly effective, but unfortunately it doesn't work.

It basically does what it should but swaps the output nibbles.

 

Try this  instead:

tmp = MIRROR_TABLE[my_byte & 0x0F];
tmp <<= 4;
my_byte = MIRROR_TABLE[my_byte >> 4]; | tmp;

 

Anders Johansson

0 件の賞賛
返信