Hi All,
On a Coldfire V1 I want to swap the bytes in a word, eg.
$1234
to
$3412
I came up with this convoluted method, is there a simpler way?
Enter with value to swap in d0
moveq #0,d1
lsl.l #8,d0
add.l d0,d1
andi.l #$FFFF,d0
lsr.l #8,d1
lsr.l #8,d1
add.l d1,d0
One final question, with the ROR & ROL Opcodes gone in the CFV1 Core, is the best option to use ASR,ASL instead and monitor the CCR(C)?
Thanks,
Ross
Either use byterev (ISA_C, if available) and use the upper 16 bits of the result, or consider:
move.l d0,d1
lsl.l #8,d0
lsr.l #8,d1
add.l d1,d0
andi.l #$FFFF,d0
Syntax errors possible, but the idea hopefully is clear.
HTH,
Johan
jbezem ,
your second idea of byte swapping (inside 16-bit word) is tested Ok. I only replaced ADD instruction with OR instruction.
The tested code in GNU notation:
/* Let d0 = 0x1234 */
move.l %d0, %d1 /* d1 = 0x1234 */
lsl.l #8, %d0 /* d0 = 0x123400 */
lsr.l #8, %d1 /* d1 = 0x12 */
or.l %d1, %d0 /* d0 = 0x123412 */
andi.l #0xFFFF, %d0 /* d0 = 0x3412 */
Well, the final thing was how to handle what would have been the ROR / ROL opcodes they had in the CPU32. The Coldfire dropped them and only has LSL/R or ASL/R, are you supposed to keep checking the CCR(C) on every shift? I can see that would get a little messy if you are rotating 6 bits (as an example).
I can't imagine Freescale would have dropped the ROR / ROL opcodes unless there was an easy way to use LSL/R or ASL/R to do the same thing?
Cheers,
Ross
> are you supposed to keep checking the CCR(C) on every shift?
Bloodhound , the solution of jbezem doesn't use CCR(C).
> I can't imagine Freescale would have dropped the ROR / ROL opcodes unless there was an
> easy way to use LSL/R or ASL/R to do the same thing?
Your question is not specific enough. Could you, please, give the specific problem to resolve in the new post?
Sorry, I'll try to explain better. It didn't help that I posted two questions!
The solution to the byte swap is perfect, thanks, my second question was on rotation of bits.
On the 68332 they had the opcodes ROR & ROL where the bits where shifted right or left.
For ROL the bits are rotated out the high-order bit, but the bits rotated out are passed back in to the low-order bit.
Eg
assume %11110000
ROL #1
becomes 11100001
ROL #1
becomes 11000011
and so on.
Or another example:
assume %11110000
ROL #4
becomes %00001111
With the Coldfire there is no ROL or ROR opcode.
Doing an ASL or LSL to the above example will always result in the high order bit being lost (though it will change the C flag).
My question is, how do you rotate a byte or a word on the Coldfire so the bits are not lost?
I don't see any equivilent opcode to the ROR / ROL so I am assuming you need to do some checking of the CCR(C) bit after each bit is shifted.
Thanks,
Ross
My solution is easily adaptable to use a different number of bits instead of 8, and
so create the equivalent of ROR/ROL.It may need a few more instructions, though.
HTH,
Johan
Thanks Johan, but I can't see how that works.
Rotate instructions are circular,your example does not seem to be that, sorry, I'll 'get it' at some point.
Cheers,
Ross
> My question is, how do you rotate a byte or a word on the Coldfire so the bits are not lost?
> I don't see any equivilent opcode to the ROR / ROL so I am assuming you need to do some
> checking of the CCR(C) bit after each bit is shifted.
> Rotate instructions are circular,your example does not seem to be that, sorry,
> 'll 'get it' at some point.
Let register d0 initially contains value 0xA3.
See the below tested code (GNU notation).
/* Rotate left by one bit the least significant byte */
lsl.l #1, %d0 /* d0 = 0x146 */
move.l %d0, %d1 /* d1 = 0x146 */
lsr.l #8, %d1 /* d1 = 0x1 */
or.l %d1, %d0 /* d0 = 0x147 */
andi.l #0xFF, %d0 /* d0 = 0x47 */
Let register d0 initially contains value 0xA3.
See the below tested code (GNU notation).
/* Rotate right by one bit the least significant byte */
move.l %d0, %d1 /* d1 = 0xA3 */
lsl.l #7, %d1 /* d1 = 0x5180 */
lsr.l #1, %d0 /* d0 = 0x51 */
or.l %d1, %d0 /* d0 = 0x51D1 */
andi.l #0xFF, %d0 /* d0 = 0xD1 */
Thanks for the suggestions everyone.
In the end I just come up with a routine that allows me to define the shift length, in this example I am manipulating 16bit values.
Before entering the rotate subroutine I load d3 with the number of bit shifts: (Rotate Right Example)
d0 contains the value to rotate and the final result.
It's annoying it uses 4 registers and lots of CPU cycles, but it will be fine for what I am trying to do.
moveq #3,d3 ; Rotate Right 3 bits
bsr.w RotateRight
;------------------------------------
RotateRight:
moveq #15,d2 ; Shifting 15 bits at a time
RotateRightLoop:
move.l d0,d1
lsl.l d2,d1
lsr.l #1,d0
or.l d1,d0
andi.l #$FFFF,d0
subi.l #1,d3
bne.b RotateRightLoop
rts
If only Freescale didn't drop the ROR / ROL opcodes from the Coldfire
Cheers,
Ross
To implement ROL for a 32-bit value, how about this for a single-pass routine using 3 registers? The "trick" is using NEG to save one register.
input parameters: d0=32-bit input value,32-bit return value d1=number of bits to rotate left move.l d0,d2 //d2=orig d0 lsl.l d1,d0 //d0=ls portion "rotated" to ms neg d1 //d1=negative orig shift amount addi.l #32,d1 //d1=shift right amount lsr.l d1,d2 //d2=ms portion "rotated" to ls or.l d2,d0 //d0=rotated result rts
By the way, how do you get code to be nicely formatted in a post?
Thanks.
To get the nice text format, select all your code and change it to the 'Courier New' font in the drop down list (Font Family).
Cheers,
Ross
I see it like this:
Shifting left 2 dwords pair D01 << 4
1) D2 = D1 >> (32-4) ; // move bits to be shifted out from D1 to D2 and shift them right
2) D0 = D0<< 4; // shift left higher order reg D0
3) D0 |= D2; // paste bits shifted out from D1
4) D1 <<= 4; // shift left lower order reg
Rotating left D0 << 4
1) D2 = D0 >> (32-4); // move bits to be shifted out to temporary register and shift them in opposite direction
2) D0 <<= 4; // shift left
3) D0 |= D2; // paste bits from temporary register
Now I feel a bit silly!
I have been using a hardcopy CF Programmers Ref Manual from 2001, the BYTEREV command is not listed in that, I just downloaded the latest 2005 revision of that document and what do you know!
Thanks,
Ross
> I have been using a hardcopy CF Programmers Ref Manual from 2001
The latest version:
ColdFire® Family
Programmer’s Reference Manual
Document Number: CFPRM
Rev. 3
03/2005
(http://www.freescale.com/files/dsp/doc/ref_manual/CFPRM.pdf?fsrch=1)
Also consider SWAP.W to swap words after .L-only BYTEREV, and
MVZ.W D0,D0 to clear upper word
Use byterev instruction