Searching \ for 'SWAPF instruction / opcode ideas' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/index.htm?key=swapf+instruction
Search entire site for: 'SWAPF instruction / opcode ideas'.

Truncated match.
PICList Thread
'SWAPF instruction / opcode ideas'
1997\07\14@202848 by John Payson

flavicon
face
> On Mon, 14 Jul 1997 10:32:05 -0500 John Payson <spam_OUTsupercatTakeThisOuTspamMCS.NET> writes:
> [...]
> >Too bad there isn't a version of "MOVF" that doesn't set flags.  The
> >opcode
> >space of the 16Cxx parts would even have room for it.  Oh well...
> >
> That wouldn't be my first choice for expanding the instruction set.  For
> that I'd like to have two instructions to move any bit directly in and
> out of the Carry bit.  This would speed up serial I/O and general
> bit-shuffling.  Also nice would be a way to complement a bit, which the
> 17CXX has.

I don't really think there's space for those instructions in the 16Cxx
opcode set.  I agree there are probably more useful instructions than
"movf" [without flags] but it would have fit very nicely in the "CLRW"
group [i.e. make it so "clrf xxx,w" maps to "movfnoflags xx,w".  At this
point that could not be changed without forcing people to re-assemble
their code (substituting "ANDLW 0" for clrw) but otherwise I think the
hardware mod would be quite simple.

As for whether the bit ops would fit... hmm... I think you'd be limitted
to one "bit"-style instruction and for that I already have an idea in
mind [though not a good name]: bmagic.

The "bmagic" instruction behaves identically to "bsf" *unless* it follows
a skip(*) in which case it would be *executed* as a "bcf".  Thus, you
could move a bit to carry via:

       btfsc   Mybyte,Mybit
        bmagic C

and could also move bits to other bits, with or without negation, etc.
The instruction would also be handy following "incfsz" and "decfsz"
instructions.

(*) Note: If a "bmagic" instruction immediately followed a "GOTO", "CALL",
"RETLW", or "RETURN", it would get executed as a "BCF" instruction [since
the CPU was trying to skip it].  Interrupt handling shouldn't pose a
problem provided that the interrupt unit allows any pending "bmagic"
instruction to execute unimpeded.

Would there be any particular use for move-bit to or from carry which
could not be handled just as well by "bmagic"?  The only one I can think
of would be shifting (where the carry-flag update is automatic) but that's
it.

{Quote hidden}

Interesting notion.  I think it would probably be better in practice to
make the "retfie" load W instead of status; this ability to load W would
also be handy in many other contexts as well.  I like the notion of having
a bit in RETxx which specifies whether it should set the interrupt-enable;
combined with the ability to fetch an operand that could be very handy.

> There is still the need to trash W in order to save STATUS at the start
> of the ISR.  If the hardware copied STATUS into a dedicated shadow
> location during the interrupt, then 2 cycles could be saved there.  Since
> nearly all interupt-driven PIC code is not nested (facilitated by the
> automatic disable), having only a single dedicated shadow location
> wouldn't be much of a problem.  If the ISR could be written to not change
> W (but still damage STATUS), then this feature and the new return and
> load instruction would cut interrupt overhead to none, or 2 cycles and
> one RAM location if W needs to be saved.

Shadow registers are a nice concept; if you don't nest interrupts the
hardware cost is probably not too unreasonable, but they allow interrupt
latency to be practically nullified.

Of course, if a "movf" were available that didn't trash flags, there'd
probably be a lot less need to save STATUS in many interrupt routines
anyway...



Anyhow, there are four more magic instructions I'd like to see...

[1] "forcef" this instruction would fetch its operand from a register,
leave it in the operand buffer, and disable the operand fetch on the next
instruction.  For example, if W held 5, then the sequence:

       forcef  Foo
       addwf   Bar,f

would place [Foo+5] into Bar.  A more typical use would be:

       forcef  foo
       movnf   Bar,f   ; movnf = move, without bothering flags

which would copy Foo into Bar without affecting anything else.

[2] "forcel"; this instruction would behave like "forcef" except that the
operand would be taken from the opcode itself [as in "xxxLW"
instructions).

[maybe] "forcew" [optional]; this instruction would place W in the operand
buffer (I don't know how easily this could be done).  If W were a readable
register, this wouldn't be needed (note: there's no real reason why WREG
needs to be writable since anything that can be done with WREG could be
done to W).

[3a] "btfgs"; goto if bit set.  This instruction would cause the next
instruction to be skipped; if the bit was set, the bits in the "pending
instruction" register would be copied to the PC.  This would allow for
jumps anywhere in the address space without need for PCLATH, and would
reduce the time required for a conditional jump from three cycles to two.

[3b] "btfgc"; [same as above, but if bit clear]

[4a] and [4b]; "btfcs" and "btfcc"; call if bit set/clear.  I'd handle
these by using the MSB of the destination address to select GOTO/CALL.

In addition, I'd like to see the following "register" enhancements:

[1] Make bit 6 of PCLATH a "goto/call" flag (bits 5 and 7 would remain
unused).  If bit 6 is set, make any writes to PC perform a CALL rather
than a GOTO.  This would save two cycles off the typical:

Springboard:
       movwf   PC
       ...
       ; put whatever in W, then...
       call    Springboard

[2] Add two new "indf" addresses for "indfi" and "indfd" which would
post-increment or post-decrement fsr.

[3] Add W as a readable register (to allow "btfsc", "rrf", etc. to be done
on it usefully).  I don't think it needs to be writable (the only
instructions which would benefit from that ability would be "bsf" and
"bcf"; these are synonymous with "andlw" or "iorlw" except that the latter
affect flags.

1997\07\15@021557 by Mike Keitz

picon face
[...]
All this talk about expanding the 16CXX instruction set is almost
certainly just talk as far as Microchip is concerned.  However it may not
be very long before other companies start bringing out "Enhanced
pic-type" chips much like all the "enhanced" 8051's out there (unlike the
8051, the PIC is a solid foundation to start enhancing)

{Quote hidden}

ANDLW 0 will clear W and set Z, MOVLW 0 will clear W without affecting Z.
So the CLRW instruction is quite unnecessary.  But it is obviously an
extension of the CLRF instruction and making it do something other than
put zero somewhere may be difficult.
{Quote hidden}

Interesting, but likely hard to do since this means tampering with the
pipeline in the PIC.  In the present design, the execution unit
apparently forces the prefetched instruction to all zeros (NOP) if a skip
is found necessary.  The bmagic instruction would require an additional
decoder to determine if the prefetched instruction is bmagic and modify
rather than clear it (probably not time to do this).  Or, rather than
clearing, a 'skip' flag could be added to the execution unit to make it
execute all instructions except bmagic as NOP.  This would likely double
the size of the microcode ROM so it could be expensive.

{Quote hidden}

That does happen a lot, for example inputting or outputting serial data
from a port pin.  I think the move to C instructions would be easier to
implement than "bmagic" since they could be done entirely in the
execution unit.  "bmagic" does make it easy to complement the bit in the
process by reversing the polarity of the test so a nice companion to the
move bit would be a complement C instruction, which could be used with
the new mvbc and btfsc to do bit-by-bit xors.  Another use is the
arithmetic shift right, which preserves the value in bit 7:
       mvbc    foo,7
       rrf     foo,f

A while ago, someone mentioned that the SPARC processor has an option to
either discard or execute the prefetched instruction after a change in
program flow.  (of course the btfsX instructions would *always* skip
since there isn't much point if they don't)  This wouldn't need much
modification to the PIC core and could make table lookups 2 cycles
faster.  With the bit set, just do

       addlw   low(table_start-1)      ;Offset into table (be
sure
                                       ;PCLATH set up)
       movwf   PCL                     ;Vector to table
       goto    $+1                     ;After MOVLW in table, do
this
                                       ;to get back here
       (next)
The table is a list of movlw's.  The instructions executed are:
fetch:   MOVWF  GOTO    MOVLW   (next)
execute: ADDLW  MOVWF   GOTO    MOVLW   (next)

Also this would call and return subroutines without missing a cycle, but
it would be necessary to move the CALL or RETURN up one, causing the
instruction after the CALL to be executed both once before and once after
the subroutine.

       (prev)
       call    sub
       movlw   5
       (next)

sub
       andlw   2               ;
       return
       addlw   1

Present PIC
fetch:  CALL    MOVLW   ANDLW   RETURN  ADDLW   MOVLW   (next)
exec:   (prev)  CALL    NOP     ANDLW   RETURN  NOP     MOVLW
No skip PIC
fetch:  CALL    MOVLW   ANDLW   RETURN  ADDLW   MOVLW
       (next)
exec:   (prev)  CALL    MOVLW   ANDLW   RETURN  ADDLW   MOVLW

This would take quite a bit of getting used to for assembler programmers
like me.  Compilers should be able to handle it better.  But, it may
waste more time and instructions turning this feature off and on than
could be saved by using it.



< about expanding RETFIE so it loads STATUS from RAM at the same time>
{Quote hidden}

I thought about that, the reason I went with STATUS is that it takes 2
instructions to save or load STATUS and only one to do W (which could be
a MOVFW since STATUS will be rewritten with the return and load).  If the
W register were mapped in file space (a highly desirable feature which
you mentioned below), then the return and load W instruction could be
made to act as a simple return by pointing it at W.  Instructions to load
and save STATUS directly may be useful in ISRs and other circumstances
but I doubt there's space for them.

>
>Shadow registers are a nice concept; if you don't nest interrupts the
>hardware cost is probably not too unreasonable, but they allow
>interrupt
>latency to be practically nullified.

A shadow for PCLATH would also be useful.  Without hardware support of a
data push-pop stack, nested interrupts are going to get too
time-consuming to be worth attempting.
{Quote hidden}

I've never had much occasion to do this, more general-purpose is an
instruction which exchanges W and a register.

       xchwf   bar     ;save W into bar
       movfw   foo     ;Get foo
       xchwf   bar     ;bar = foo, recover old W

In the example above, the pesky MOVFW will affect Z.  But, if the value
of foo didn't need to be preserved the movfw could be replaced with an
xchwf, leaving the old value of bar in foo (a complete exchange of foo
and bar).  The xchwf could also be the no-flags load W, if it didn't
matter that the value in RAM was lost (such as when returning from an
interrupt).

>[2] "forcel"; this instruction would behave like "forcef" except that
>the
>operand would be taken from the opcode itself [as in "xxxLW"
>instructions).

The place I would find this useful would be for resetting a counter, e.g.
a counter that goes from 40 down to 1 then starts at 40 again:

       decf    counter,f       ;Decrement counter
       forcel  .40
       skpnz                   ;Did counter reach 0?
       movf    bar,f           ;Yes, restart it.

But this won't work with your forceX instructions since they only keep
for one instruction.  So may as well put the value in W and save it if
necessary.  A decfsnz instruction as on the 17CXX would be useful in
situations like these.
{Quote hidden}

This is a real mess, you're introducing two-word instructions now.  So an
entirely new data path from the instruction register to the PC would need
to be added, along with logic to not attempt to execute the program words
which are long addresses rather than instructions.

What may be nice would be versions of goto and call that use W rather
than PCLATH for the high address.  This would make long gotos or calls
quicker but then it wouldn't be possible to pass parameters in W.

{Quote hidden}

The no-skip logic would also allow 4-cycle table access, albeit with a
lot more confusion.  The place to control that is probably also one of
the high bits of PCLATH.

I've had a couple of times when a no-return RETURN would be useful, i.e.
it would pop (and ignore) the top address on the stack so the last CALL
would be effectively converted to a goto and the next RETURN would go to
the second to last CALL.
>
>[2] Add two new "indf" addresses for "indfi" and "indfd" which would
>post-increment or post-decrement fsr.

Not sure if this is worth dedicating much hardware and file space to.
>
>[3] Add W as a readable register (to allow "btfsc", "rrf", etc. to be
>done
>on it usefully).  I don't think it needs to be writable (the only
>instructions which would benefit from that ability would be "bsf" and
>"bcf"; these are synonymous with "andlw" or "iorlw" except that the
>latter
>affect flags.

This is very useful for the test and rotate, such as multiplying or
dividing by a constant to generate an address.
>

1997\07\15@035439 by STEENKAMP [M.ING E&E]

flavicon
picon face
[Major Snip]

{Quote hidden}

I would, most of all, appreciate an add with carry and subtract with
borrow.  This would __greatly__ simplify multi byte arithmetic!  But,
alas...

Niki

1997\07\15@045640 by John Payson

flavicon
face
> All this talk about expanding the 16CXX instruction set is almost
> certainly just talk as far as Microchip is concerned.  However it may not
> be very long before other companies start bringing out "Enhanced
> pic-type" chips much like all the "enhanced" 8051's out there (unlike the
> 8051, the PIC is a solid foundation to start enhancing)

Right.  I think, though, the 16Cxx is a more solid foundation than the
17Cxx.  The 17Cxx adds a bunch of stuff, but there seems IMHO to be less
consistency about it.

{Quote hidden}

I don't know how Microchip actually implements the guts of their PIC, but
I would expect that it shouldn't be that hard a mod.  In particular, you
don't need to worry about the change in functionality until after the
operand fetch; there should be plenty of time in the pipeline to decode
that if the most significant 7 bits are "x", they should be interpreted to
do "y".

{Quote hidden}

I guess it's possible that Microchip physically zeroes the fetched
instruction, but I would think it easier to add a "skip" state to the
unit's state machine.  Given that such things need to be handled to
process interrupts and such properly, that would probably be my choice.
Your point, however, is well-taken.  Perhaps "BMAGIC" could perform a bit
test and flip a bit in the next prefetched instruction if true?

{Quote hidden}

Note that the above can also be done as:

       rlf     foo,w
       rrf     foo,f

if you don't mind trashing W.

I guess my biggest problem with load/store C is that in many applications
it's desirable to invert a bit in the process of moving it, and you end up
having to use a lot of opcode space to support moving bits around.  If
adding one instruction would extend the functionality of others to allow
moving bits, I think that would be better.

> A while ago, someone mentioned that the SPARC processor has an option to
> either discard or execute the prefetched instruction after a change in
> program flow.  (of course the btfsX instructions would *always* skip
> since there isn't much point if they don't)  This wouldn't need much
> modification to the PIC core and could make table lookups 2 cycles
> faster.

Delayed jumps are nice.  Unless you have seperate opcodes for delayed and
non-delayed jumps, however, they're a pain.  I personally despise flags
which make major changes to how instructions operate; the delay-jumps flag
would probably rank between the '251's mode flag and the 6502's "decimal"
flag on the annoyance scale.

>         movwf   PCL                     ;Vector to table
>         goto    $+1                     ;After MOVLW in table, do

There's a problem with this--it's not obvious, but it can bite and hard.
Suppose an interrupt occurs as the "movwf" is about to be executed [so it
will take control just after].  What address should be pushed on the
return stack?

On the 12-bit cores, though, this would have been a good technique since
there were no interrupts to contend with and it would have allowed RETLW
to be replaced with something else useful (like ADDLW).

{Quote hidden}

I think W is probably easier to implement in hardware, and I think that in
the non-interrupt case W will be useful much more often.

> >Shadow registers are a nice concept; if you don't nest interrupts the
> >hardware cost is probably not too unreasonable, but they allow
> >interrupt
> >latency to be practically nullified.
>
> A shadow for PCLATH would also be useful.  Without hardware support of a
> data push-pop stack, nested interrupts are going to get too
> time-consuming to be worth attempting.

Yeah, a shadow for PCLATH might be nice too, but W and PSW are the
essential ones.  Those are needed in 90-99% of ISR's; PCLATH is needed
much more seldom.

{Quote hidden}

But as your example itself illustrates, the exchange instruction doesn't
help as much as the "forcef" instruction.  In addition, the "forcef"
version would avoid the side-effects posed by your "xchwf" example above
and would (conjecture here) probably be easier to implement.

Compared with "movfp" and "movpf" (both of which use GOBS of opcode space)
I think "forcef" would be just as useful (not as fast as movpf/movfp, but
not restricted in addressing ability).  I don't know whether you'd use
that instruction, but there are many spots (esp. in ISR's) where the
ability to move register to register without affecting W or PSW would be
very nice indeed.

{Quote hidden}

How about...

       decfsz  counter,f
       btfsc   KZ,0            ; Something that will always be clear
        forcel .40
       movnf   counter,f       ; Move without setting flags

Note that the "movnf" always happens, but if the counter wasn't
decremented to zero the "forcel" won't be executed and the "movnf" will
have no effect.  Note that in the above code, neither W nor PSW is
affected; it could be used in an interrupt without saving those registers.

{Quote hidden}

I don't think it would be that bad; true there would have to be a
dedicated data path from the pending instruction to the PC, but that
shouldn't be terribly hard.  As for avoiding an attempt to execute the
instruction, the only case I can see where that would be problematical
would be with my original proposed "bmagic" instruction; otherwise the
same type of logic could be used as handles "ordinary" skips.

I guess if Microchip is using a discrete-logic multiplexor on the PC,
adding the other data path could be a pain; if they're using a pass-gate
mux, however, I would think it quite feasible.

> What may be nice would be versions of goto and call that use W rather
> than PCLATH for the high address.  This would make long gotos or calls
> quicker but then it wouldn't be possible to pass parameters in W.

Ehh... I don't know about that.  On a 4K part, at most one BSF/BCF is
needed to set PCLATH before a GOTO or CALL; on an 8K part two would be
needed.  Compared with having to load W, I think PCLATH is more
convenient.

{Quote hidden}

I have seen code which used RLF or RRF on PCLATH (in computing table
values).  Such code could break if anything other than bit 6 were used.  I
think having a "call-mode" bit there would be nicer than a skip-select
bit, but it's probably just a matter of taste.

> I've had a couple of times when a no-return RETURN would be useful, i.e.
> it would pop (and ignore) the top address on the stack so the last CALL
> would be effectively converted to a goto and the next RETURN would go to
> the second to last CALL.

I've been in this situation too.

> >[2] Add two new "indf" addresses for "indfi" and "indfd" which would
> >post-increment or post-decrement fsr.
>
> Not sure if this is worth dedicating much hardware and file space to.

Perhaps; perhaps not.  IMHO it would have been a better investment than
having bits in ALUSTA to control those effects.

{Quote hidden}

Right.  Any reason it should be writable (as a register), though?  Doing
so requires adding another write-data path for IMHO very little payoff.

1997\07\15@050055 by John Payson
flavicon
face
> I would, most of all, appreciate an add with carry and subtract with
> borrow.  This would __greatly__ simplify multi byte arithmetic!  But,
> alas...

True, but even without those a 4-byte add isn't too bad...

; D<-D+S
       movf    S0,w
       addwf   D0,f
       movf    S1,w
       btfsc   C
        incfsz S1,w
        addwf  D1,f
       movf    S2,w
       btfsc   C
        incfsz S2,w
        addwf  D2,w
       rlf     KZ,w    ; KZ == known-zero address
       addwf   S3,w
       addwf   D3,f

Total of 13 instructions, 13 cycles.  Note that if the destination is not
one of the sources, you should copy the middle bytes from source to
destination and then do the add.

1997\07\15@134245 by Mike Keitz

picon face
On Tue, 15 Jul 1997 03:50:44 +0000 John Payson <.....supercatKILLspamspam@spam@MCS.COM> writes:

{Quote hidden}

Combining the xchwf with a no-status movfw would avoid this, but then
that's 2 new instructions.  Really there'd be no reason for movfw to ever
affect status if there were another status bit which indicated if the
value in W were presently zero.  There'd be no need to save this bit
since it would always track the value in W.  (for the rare cases where
the other Z bit should indicate if w=0, use a iorlw 0 to set it.)
>
Most of this comes from a fascination with being able to move data
without using the W register (whose primary purpose is to move data).
Since you're proposing 2-word instructions, I'll propose something
equally complicated, a data stack.  If there were a data push-pop stack
to make saving W easier then it wouldn't be OK to move data through W as
intended.  There could be a version of movfw which puts the old W on the
stack, and a movwf which pops the stack.  These could be the 'push' and
'pop' instructions by pointing them to a scratch location.  Or a move foo
into bar without affecting W would be
       movfwp  foo
       movwfp  bar
The ability to pass parameters to subroutines on the stack would be
tremendous especially for compiler writers who are used to doing that
anyway, and a series of movfwp's could be used to quickly collect data
from RAM or SFRs and place it on the stack.  Stacking W and STATUS during
an ISR would be simple too:
       movfwp  STATUS          ;W->stack, STATUS ->W
       movfwp  scratch         ;STATUS - stack
[isr]
       movwfp  scratch         ;stack (old STATUS) - > W
       movwfp  STATUS          ;old STATUS -> STATUS, stack
(old W) - > W
       retfie

Having the data stack a dedicated special space may be simpler to make
but to get the full advantage it should be in RAM with an accessable
pointer.  Even without adding special instructions, there could be two
SFR's of SP and ST.  SP is like another FSR and ST is like another INDF.
The SP register should have some page-select capability so the stack
could be way off in an otherwise unused When reading ST, SP is
postincremented, and when writing ST it is predecremented.  This would
allow a subroutine to point FSR somewhere in the stack and work on data
directly there, or to tear parameters off the stack by adding a constant
to SP.

1997\07\15@222223 by Dmitry Kiryashov

flavicon
face
Hello John .


> > I would, most of all, appreciate an add with carry and subtract with
> > borrow.  This would __greatly__ simplify multi byte arithmetic!  But,
> > alas...
>
> True, but even without those a 4-byte add isn't too bad...
>
> ; D<-D+S
>         movf    S0,w
>         addwf   D0,f
Ok.

>         movf    S1,w
>         btfsc   C
>          incfsz S1,w
>          addwf  D1,f

Stop. For example S1=0xFF , D1=0x00 , Carry=1 . After executing your
code result will
be equal 0x00 with Carry=0 not =1 . It's error . In my code to correct
this situation
I save previous Carry's in S1 .

       movfw   S1
       skpnc
       addlw   1
       rlf     S1,F
       addwf   D1,F
       btfsc   S1,0
       setc

... etc


{Quote hidden}

WBR Dmitry.

1997\07\16@011616 by John Payson

flavicon
face
> > True, but even without those a 4-byte add isn't too bad...
> >
> > ; D<-D+S
> >         movf    S0,w
> >         addwf   D0,f
> Ok.
>
> >         movf    S1,w
> >         btfsc   C
> >          incfsz S1,w
> >          addwf  D1,f
>
> Stop. For example S1=0xFF , D1=0x00 , Carry=1 . After executing your
> code result will
> be equal 0x00 with Carry=0 not =1 .

Let's see....

Instr.  Carry   W       D1  [values given after instruction]
movf    set     FF      00
btfsc   set     FF      00
incfsz  set     00      00
[skip]  set     00      00

D1 equals zero, as it should, and carry is set, as it should be.  I didn't
come up with that piece of tricky code, but it really does work!

{Quote hidden}

That's seven instructions longer.  What's the payout from the extra
instructions?

{Quote hidden}

BTW, did you notice how I also saved a cycle on the last stage where
carry-out isn't needed?

1997\07\16@033937 by Dmitry Kiryashov

flavicon
face
Hello John.

{Quote hidden}

It's code that really have a bug ! Why ? So you listing above looks
right .
But after next operation addwf D1,F - Carry will set =0 not remain =1 .
It's error sitiuation , because when you will add S2 to D2
you will do it with wrong prev Carry value .

> > It's error . In my code to correct this situation I save previous Carry's in
S1 .
{Quote hidden}

It's wrong magic ;( It's example that explain why code suddenly start
to do strange things in some situation . Payout ? Fully correct code
at any situation for any n-th byte arithmetic (becouse true Carry
adding)

{Quote hidden}

The russian proverb say:
Sometimes the more slow speed you go than greater way you will pass . ;)

WBR Dmitry.

1997\07\16@043451 by John Payson

flavicon
face
{Quote hidden}

But the "addwf" isn't executed.  The "incfsz" increments the $FF to zero,
and thus skips the following instruction (the add).

> It's wrong magic ;( It's example that explain why code suddenly start
> to do strange things in some situation . Payout ? Fully correct code
> at any situation for any n-th byte arithmetic (becouse true Carry
> adding)

The magic code I supplied is tricky, but if you try it, the carry is in
fact handled correctly in every case.

> > > >         movf    S2,w
> > > >         btfsc   C
> > > >          incfsz S2,w
> > > >          addwf  D2,w
> > > >         rlf     KZ,w    ; KZ == known-zero address
> > > >         addwf   S3,w
> > > >         addwf   D3,f
> > > >
> > > > Total of 13 instructions, 13 cycles.  Note that if the destination is
not
> > > > one of the sources, you should copy the middle bytes from source to
> > > > destination and then do the add.
>
> The russian proverb say:
> Sometimes the more slow speed you go than greater way you will pass . ;)

But if you know the right magic you can save cycles.

1997\07\16@043654 by STEENKAMP [M.ING E&E]

flavicon
picon face
{Quote hidden}

No, I disagree.  If C was not set, the incfsz will be skipped and the
addwf will be done, which is correct.  If C was set, then the incfsz will
be done and carry will be added to S1, which, if this doesn't cause a
carry will be added to D1 in the addwf.  This may create another carry
that will propagate to S2.  If S1 did oveflow, then we are in effect
adding 0 to D1 and propagating a carry to S2.  So, it all makes sense.

There is, though, a small error (IMHO):
( Original Code: )
>; D<-D+S
>        movf    S0,w
>        addwf   D0,f
>        movf    S1,w
>        btfsc   C
>         incfsz S1,w
>         addwf  D1,f
>        movf    S2,w
>        btfsc   C
>         incfsz S2,w
All is fine.
>         addwf  D2,w
Shouldn't this be addwf  D2,F ??
>        rlf     KZ,w    ; KZ == known-zero address
>        addwf   S3,w
>        addwf   D3,f

Quite nifty piece of code though!

Niki

1997\07\16@053528 by Frank A. Vorstenbosch

flavicon
face
On Tue, 15 Jul 1997 Mike Keitz <mkeitzspamKILLspamJUNO.COM> wrote:
>
> Most of this comes from a fascination with being able to move data
> without using the W register (whose primary purpose is to move data).
> Since you're proposing 2-word instructions, I'll propose something
> equally complicated, a data stack.  If there were a data push-pop stack
> to make saving W easier then it wouldn't be OK to move data through W as
> intended.

Why not simply put stuff on the instruction stack?  This would require
a connection between W and the stack, obviously, but not the (potentially
huge) increase in logic needed to allow for pre-decrementing and post-
incrementing FSR2.  All you'd need would be PUSHW and POPW instructions,
and then your interrupt handler would look like this:

Interrupt:      pushw
               swapf   status,w
               pushw

               .
               .
               .

               popw
               movwf   tmp
               swapf   tmp,w
               movwf   status
               popw
               retfie

Still some nasty shuffling required to get the status register correct
(including a temporary register??  someone else may know better) so
perhaps a PUSH (and POP) for the status register could be implemented.

Oh, well, just wishful thinking.

Frank

------------------------------------------------------------------------
Frank A. Vorstenbosch                           Phone:  +44-181-636 3391
Electronics & Software Engineer                    or:  +44-181-636 3000
Eidos Technologies Ltd., Wimbledon, London      Mobile:  +44-976-430 569

1997\07\16@100641 by Mike Keitz

picon face
On Wed, 16 Jul 1997 06:25:54 +0400 Dmitry Kiryashov <.....zewsKILLspamspam.....AHA.RU> writes:
>Hello John .

>
>>         movf    S1,w
>>         btfsc   C
>>          incfsz S1,w
>>          addwf  D1,f
>
>Stop. For example S1=0xFF , D1=0x00 , Carry=1 . After executing your
>code result will
>be equal 0x00 with Carry=0 not =1 . It's error . In my code to correct
>this situation
>I save previous Carry's in S1 .

Look closer.  Notice that the operation on S1 if C is set is incfsz:
Increment f, *skip if (now) zero*.  If S1+1 =0, the add will be skipped
(what's the point of adding 0?).  So if S1=FF, C in = 1, the incfsz will
be executed, and it will skip.  C will still be 1 because the add was not
executed.  And the sum will be correct also because zero would have been
added.  This code works.  Some of the Microchip examples use incf
instead, which is wrong, though it does work for a 16 bit add since the
carry out is usually not used.

1997\07\16@125451 by Dmitry Kiryashov

flavicon
face
Hello John .

> But the "addwf" isn't executed.  The "incfsz" increments the $FF to zero,
> and thus skips the following instruction (the add).

John . Please excuse me my dummy obstinacy ;)
I was not look carefully into your code and
I was think about INCF operation not INFSZ . ;(

So , I was wrong stupid one .

> But if you know the right magic you can save cycles.

Faster than your example I really don't know .

WBR Dmitry.

1997\07\16@213125 by blunn

flavicon
face
Bob Lunn
07/17/97 11:31 AM


Dmitri, are you now happy that the multi-byte addition shown
on the piclist is correct?  It *does* correctly propogate carries
through all the bytes of the result, and your criticism of the
algorithm is wrong.

If you are still unsure on this point, I will be happy to discuss
it further with you (took me some time to convince myself of
its correctness!).

___Bob

1997\07\17@035839 by mike

flavicon
picon face
In message  <EraseME1023F4E4338spam_OUTspamTakeThisOuTfirga.sun.ac.za> PICLISTspamspam_OUTMITVMA.MIT.EDU writes:
>
> I would, most of all, appreciate an add with carry and subtract with
> borrow.  This would __greatly__ simplify multi byte arithmetic!  But,
> alas...
>
> Niki
>

I agree whole-heartedly with this one.

Regards,


Mike Watson

1997\07\17@234624 by Dmitry Kiryashov

flavicon
face
blunn@KEYCORP.COM.AU wrote:

> Dmitri, are you now happy that the multi-byte addition shown
> on the piclist is correct?  It *does* correctly propogate carries
> through all the bytes of the result, and your criticism of the
> algorithm is wrong.
>
> If you are still unsure on this point, I will be happy to discuss
> it further with you (took me some time to convince myself of
> its correctness!).

Yes , I was wrong . I was thinking about incf not incfsz instruction .
It was my inattentaion ;(

WBR Dmitry.

1997\07\18@042723 by Dmitry Kiryashov

flavicon
face
Hello John .

To correct my recent mistake I offer the same idea as your one ,
but for multibyte substraction .

>         movf    S1,w
>         btfsc   C
>          incfsz S1,w
>          addwf  D1,f

After thinking some times about this tricky code I can tell:
It's really one from finest(beautiful) PIC code construction .


My example for multibyte substraction :

   ; D1 = D1 - S1 - borrow
   ; before/after C = 0 - subtraction was with borrow
   ; before/after C = 1 - subwf was without borrow

...
   MOVFW  S1
   SKPC
   DECFSZ S1,W
   SUBWF  D1,F
...

WBR Dmitry.

P.S. I get just another confirmation that PIC code set is not bad ;)

More... (looser matching)
- Last day of these posts
- In 1997 , 1998 only
- Today
- New search...