No exact or substring matches. trying for part
PICList
Thread
'[PICLIST] Challenge: Shifting by a variable amount'
2001\09\26@012046
by
Scott Dattalo
In C:
unsigned char x;
unsigned char y;
...
x <<= y;
How would you do this in PIC assembly?
This has been discussed here before (but I couldn't find it in the
archives) and IIRC a 12 cycle solution was found (by Dmitry?). I've got a
12-cycle solution, but thought it would be interesting to propose this as
a challenge. (The winner may simply find the answer in the archives :).
Scott
--
http://www.piclist.com hint: The PICList is archived three different
ways. See http://www.piclist.com/#archives for details.
2001\09\26@020211
by
Gennette, Bruce
Is this what you want ?
movlw amount_to_shift
movwf y
shiftit
rlf x, f
decfsz y, f
goto shiftit
nextcode
Bye.
{Original Message removed}
2001\09\26@030131
by
Regulus Berdin
Hi Scott,
I'll try (untested):
;x <<= y;
clrc
btfsc y,0
rlf x,f ;x = x*2
clrc
rlf x,w ;w = x*2
addwf x,w ;w = w+x = x*2+x = x*3
btfsc y,1
addwf x,f ;x = w+x = x*3+x = x*4
swapf x,w
andlw 0xF0
btfsc y,2
movwf x ;x=x*8
regards,
Reggie
{Original Message removed}
2001\09\26@082349
by
Stephen Webb
> movlw amount_to_shift
> movwf y
> shiftit
> rlf x, f
> decfsz y, f
> goto shiftit
I think you may want to add:
shiftit
bcf status,c
...
...
goto shiftit
The rlf rotates through the carry, and we just want a shift, so it's
necessary to clear the carry bit before each rotate.
-Steve
--
http://www.piclist.com hint: The PICList is archived three different
ways. See http://www.piclist.com/#archives for details.
2001\09\26@091225
by
Dmitry Kiryashov
Hi Scott.
What range is original X and Y ? 8 bits ( byte ) ?
What range is result ? Byte as well ?
More clarity is required ;)
WBR Dmitry.
{Original Message removed}
2001\09\26@104743
by
Scott Dattalo
|
On Wed, 26 Sep 2001, Regulus Berdin wrote:
Reggie, welcome back.
{Quote hidden}> Hi Scott,
>
> I'll try (untested):
>
> ;x <<= y;
>
> clrc
> btfsc y,0
> rlf x,f ;x = x*2
>
> clrc
> rlf x,w ;w = x*2
> addwf x,w ;w = w+x = x*2+x = x*3
> btfsc y,1
> addwf x,f ;x = w+x = x*3+x = x*4
>
> swapf x,w
> andlw 0xF0
> btfsc y,2
> movwf x ;x=x*8
Interesting. Mine is slightly different and is suitable for this type of
operation:
unsigned char x;
unsigned char y;
unsigned char z;
z = x << y;
swapf x,w
andlw 0xf0
btfss y,2
movf x,w
movwf z
btfss y,0
addwf z,f
rlf z,w
andlw 0xfe
addwf z,w
btfsc y,1
addwf x,f
-----------------
Dmitry, The "unsigned char" implies an 8-bit register (at least on all of
the C compilers that target a PIC that I know of). Only the lower three
bits of the shift count are examined. It looks like an additional 4
instructions would be required to verify that the upper bits are not set.
------
Now, to do the same thing in a looping snippet:
; if x and z are different registers
movf x,w
movwf z
comf y,w ; the shift count
; note w= 0-y+1
rrf z,f
loop:
rlf z,f
addlw 1
skpc
goto loop
Scott
--
http://www.piclist.com hint: The PICList is archived three different
ways. See http://www.piclist.com/#archives for details.
2001\09\27@012202
by
jeethur
Now thats mere rotation, shift is needed,so add a clrc. Even then,
Scott was talking of the number of Cycles. Your thing would take
2 + ( (5 * n) - 1 ) cycles. Where n is the number of shifts.
21 cycles for shifting 4 bits.
I've got a small little optimization to this. When you shift more than
or eqal to 4 times, a swapf would make things a lot simpler.
Herez my way of doing it.
<code>
movlw amount_to_shift
movwf y
movlw 0x04
subwf y,w
skpc
goto slow_shift ; 8 cycles
; 6 cycles
swapf x,w
andlw 0xF0
movwf x
movlw 0x04
subwf y,f ; 11 cycles
slow_shift
tstf y
skpnz
goto shift_done ; 16 cycles
clrc
rlf x,f
decf y,f
goto slow_shift
shift_done
</code>
It takes 16 cycles for shift by 4. Not the best solution.
But hey I just coded it on the fly.
Jeethu Rao
> {Original Message removed}
2001\09\27@082016
by
Dmitry Kiryashov
|
Hi guys. ;)
{Quote hidden}> > Hi Scott,
> >
> > I'll try (untested):
> >
> > ;x <<= y;
> >
> > clrc
> > btfsc y,0
> > rlf x,f ;x = x*2
> >
> > clrc
> > rlf x,w ;w = x*2
> > addwf x,w ;w = w+x = x*2+x = x*3
> > btfsc y,1
> > addwf x,f ;x = w+x = x*3+x = x*4
> >
> > swapf x,w
> > andlw 0xF0
> > btfsc y,2
> > movwf x ;x=x*8
This will not work. swapf block has to be first.
Otherwise you'll be possibly destroying right
sequency of bits.
{Quote hidden}> Interesting. Mine is slightly different and is suitable for this type of
> operation:
>
>
> unsigned char x;
> unsigned char y;
> unsigned char z;
>
>
> z = x << y;
>
>
> swapf x,w
> andlw 0xf0
> btfss y,2
> movf x,w
>
> movwf z
> btfss y,0
> addwf z,f
>
> rlf z,w
> andlw 0xfe
> addwf z,w
> btfsc y,1
> addwf x,f
I think not x but z is suggested in last operation.
> Dmitry, The "unsigned char" implies an 8-bit register (at least on all of
> the C compilers that target a PIC that I know of). Only the lower three
> bits of the shift count are examined. It looks like an additional 4
> instructions would be required to verify that the upper bits are not set.
Yep. I was asking this sort of question to clarify is this
arithmetical shift operation (left shift with incoming zeroes)
or logical (from carry rolled over from highest bit)
Anyway number 12 is still looking magical doesn't it ? ;)
WBR Dmitry.
--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email spam_OUTlistservTakeThisOuT
mitvma.mit.edu with SET PICList DIGEST in the body
2001\09\27@100149
by
Scott Dattalo
On Thu, 27 Sep 2001, Dmitry Kiryashov wrote:
{Quote hidden}> >
> > unsigned char x;
> > unsigned char y;
> > unsigned char z;
> >
> >
> > z = x << y;
> >
> >
> > swapf x,w
> > andlw 0xf0
> > btfss y,2
> > movf x,w
> >
> > movwf z
> > btfss y,0
> > addwf z,f
> >
> > rlf z,w
> > andlw 0xfe
> > addwf z,w
> > btfsc y,1
> > addwf x,f
>
> I think not x but z is suggested in last operation.
You're right, of course.
> Anyway number 12 is still looking magical doesn't it ? ;)
Mystical!
Scott
--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email .....listservKILLspam
@spam@mitvma.mit.edu with SET PICList DIGEST in the body
2001\09\27@104834
by
jeethur
Hey Scott, are you doing this for SDCC,
Since shifts are very essential in C ?
I just got this thought now!
Jeethu Rao
> {Original Message removed}
2001\09\27@110802
by
Scott Dattalo
|
On Thu, 27 Sep 2001, Jeethu Rao wrote:
> Hey Scott, are you doing this for SDCC,
> Since shifts are very essential in C ?
> I just got this thought now!
:).
void shift_left_var(void)
{
achar0 <<= achar1;
}
produces:
(copious debugging junk left in...)
;_shift_left_var:
_shift_left_var ;Function start
; 1 exit point
;;ic
;; rotate2.c 25
;; *** resultRemat 2320
;; *** genLeftShift 6032
;; 607
;; 630 - true symop
;; *** aopForSym 341
;; 427 sym->rname = _achar1, size = 1
;mov b,_achar1
;inc b
;; 607
;; 630 - true symop
;; *** aopForSym 341
;; 427 sym->rname = _achar0, size = 1
;; 607
;; 623
SWAPF _achar0,W
ANDLW 0xf0
BTFSS _achar1,2
MOVF _achar0,W
MOVWF _achar0
BTFSS _achar1,0
ADDWF _achar0,F
RLF _achar0,W
ANDLW 0xfe
ADDWF _achar0,W
BTFSC _achar1,1
ADDWF _achar0,F
Yes I'm doing this for SDCC. This code has been tested in the regression
suite as well.
I thought about posting the snippets for shifting by a constant amount
too.
Scott
--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listserv
KILLspammitvma.mit.edu with SET PICList DIGEST in the body
More... (looser matching)
- Last day of these posts
- In 2001
, 2002 only
- Today
- New search...