Searching \ for 'Automatic call optimization macro' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/index.htm?key=automatic+call+optimization
Search entire site for: 'Automatic call optimization macro'.

Truncated match.
PICList Thread
'Automatic call optimization macro'
1998\02\04@192857 by Morgan Olsson

picon face
I have mentioned it before, and now I«ve tried it:

; Following macro I want to use instead of call instructions when I«m not
sure
; if the routine I call (target) is in the same page as the calling routine.
; Writing include files I don«t want to decide either, as they should be
universal.
; The macro senses if there is need to set PCLATH.
; If setting PCLATH (corrupt W) it saves and restores W in Wtemp if Wtemp<>0.
; So we have fully automatic code optimization!
CALLPAGE        macro target,Wtemp
       if high target == high $    ;No need to change PCLATH
               messg "CALLPAGE evaluated to simple call"
       else
               if Wtemp == 0 ;Do not save and reload W, +2 instructions
                       movlw   high target
                       movwf   PCLATH
               else ;Save and restore W using register adress Wtemp, +4 instr.
                       movwf   Wtemp
                       movlw   high target
                       movwf   PCLATH
                       movf    Wtemp,W
               endif
       endif
       call target
       endm

;Of course, we could also make a GOPAGE macro the same way.

I think it would work really great if it was not for the compiler:
I get an almost endless list of errors like
"
Error[116]   C:\MO\PROG\PIC\P\BAL01\MONIT.ASM 147 : Address label
duplicated or different in second pass (monitio)
Error[116]   C:\MO\PROG\PIC\P\BAL01\MONIT.ASM 150 : Address label
duplicated or different in second pass (monitiorot)
Error[116]   C:\MO\PROG\PIC\P\BAL01\MONIT.ASM 160 : Address label
duplicated or different in second pass (monitiorotutH)
Error[116]   C:\MO\PROG\PIC\P\BAL01\MONIT.ASM 162 : Address label
duplicated or different in second pass (monitiorotutOK)
"
etc, etc...
Well, the macro seem to work, as the adresses change.
Nice, that is the goal, right.

So, I just want the compiler to run more passes, and we are there!
But how to make it run more passes ??
Are there other obstacles?

Thank you in advance.
/Morgan

PS   Strange... the nice song "Write in C" keep running in my mind more and
more...  But I do«t have time to learn C now; deadline monday... probably
meaning I«m dead tuesday...   DS
/  Morgan Olsson, MORGANS REGLERTEKNIK, SE-277 35 KIVIK, Sweden \
\  spam_OUTmrtTakeThisOuTspaminame.com, ph: +46 (0)414 70741; fax +46 (0)414 70331    /

1998\02\04@201950 by Andrew Warren

face
flavicon
face
Morgan Olsson <.....PICLISTKILLspamspam@spam@MITVMA.MIT.EDU> wrote:

> Following macro I want to use instead of call instructions when
> I'm not sure if the routine I call (target) is in the same page as
> the calling routine.
> ....
> I think it would work really great if it was not for the compiler: I
> get an almost endless list of errors like
> " Error[116] C:\MO\PROG\PIC\P\BAL01\MONIT.ASM 147 : Address label duplicated
or
> different in second pass (monitio)"

   Right.  As I said two weeks ago, "Be careful, when you write
   your macros, to avoid forward-reference problems."

> So, I just want the compiler to run more passes, and we are there!
> But how to make it run more passes ??

   You can't.  The only way to avoid this forward-reference
   problem, using your macro, is to ensure that each subroutine
   appears in your source code BEFORE the line that CALLs it.

   -Andy

=== Andrew Warren - fastfwdspamKILLspamix.netcom.com
=== Fast Forward Engineering - Vista, California
=== http://www.geocities.com/SiliconValley/2499

1998\02\05@161918 by wouter van ooijen

picon face
Nice concept, but wat you want is not that easy with MPASM.

MPASM makes one pass (pass one) to determine the locations of all labels,
and a final one (pass two) to generate the code. In pass two it checks
whether all labels still have the same value. If that is not the case, it
bails out (it should, because it could have created wrong code).

I can think of some solutions, but those are much more complex than what
you did.
You could try:
- use a macro declare_label to declare the labels, and keep your own label
administration
- reform all procedures into macros, and expand them in inverse-call order
in the second pass only
- try to find a solution which always expands to the same number of
instructions

By the way, you could replace your callpage macro obfusciated call macro.
If I remember well the principle is:

_call macro x
endm

#define call _call

Within the macro _call you'll have to undefine call before you can use the
normal call,
and after that you must define it again.

I have used these kind of constructs to make if then else and looping
macro's,
but I finally gave up because assembling took too long. I might try it
again some
time with my new PC.

----------
> From: Morgan Olsson <.....mrtKILLspamspam.....INAME.COM>
> To: EraseMEPICLISTspam_OUTspamTakeThisOuTMITVMA.MIT.EDU
> Subject: Automatic call optimization macro
> Date: Thursday, February 05, 1998 01:25
>
> I have mentioned it before, and now I«ve tried it:
>
> ; Following macro I want to use instead of call instructions when I«m not
> sure
> ; if the routine I call (target) is in the same page as the calling
routine.
> ; Writing include files I don«t want to decide either, as they should be
> universal.
> ; The macro senses if there is need to set PCLATH.
> ; If setting PCLATH (corrupt W) it saves and restores W in Wtemp if
Wtemp<>0.
> ; So we have fully automatic code optimization!
> CALLPAGE        macro target,Wtemp
>         if high target == high $    ;No need to change PCLATH
>                 messg "CALLPAGE evaluated to simple call"
>         else
>                 if Wtemp == 0 ;Do not save and reload W, +2 instructions
>                         movlw   high target
>                         movwf   PCLATH
>                 else ;Save and restore W using register adress Wtemp, +4
instr.
{Quote hidden}

and
> more...  But I do«t have time to learn C now; deadline monday... probably
> meaning I«m dead tuesday...   DS
> /  Morgan Olsson, MORGANS REGLERTEKNIK, SE-277 35 KIVIK, Sweden \
> \  mrtspamspam_OUTiname.com, ph: +46 (0)414 70741; fax +46 (0)414 70331    /

1998\02\06@103527 by Tom Mariner

flavicon
face
Strangely enough, the construct you detail (including or not including code
depending upon program location) used to work in ancient versions of MPASM.
We used it effectively to dramatically reduce program size and complexity
until it was removed in the interests of modern assembler construction.
Although I would love to have it back, the MPLAB / MPASM / etc. combo make
the job so much easier that we will live with it!

Tom

> > ; Following macro I want to use instead of call instructions when I?m
not
> > sure
> > ; if the routine I call (target) is in the same page as the calling
> routine.
> > ; Writing include files I don?t want to decide either, as they should
be
> > universal.
> > ; The macro senses if there is need to set PCLATH.
> > ; If setting PCLATH (corrupt W) it saves and restores W in Wtemp if
> Wtemp<>0.
> > ; So we have fully automatic code optimization!
> > CALLPAGE        macro target,Wtemp
> >         if high target == high $    ;No need to change PCLATH
> >                 messg "CALLPAGE evaluated to simple call"
> >         else
> >                 if Wtemp == 0 ;Do not save and reload W, +2
instructions
> >                         movlw   high target
> >                         movwf   PCLATH
> >                 else ;Save and restore W using register adress Wtemp,
+4
{Quote hidden}

1998\02\06@170944 by Alexandr A. Redchuck

flavicon
face
> > > ; The macro senses if there is need to set PCLATH.
> > > ; If setting PCLATH (corrupt W) it saves and restores W in Wtemp if
> > Wtemp<>0.
> > > ; So we have fully automatic code optimization!
> > > CALLPAGE        macro target,Wtemp
> > >         if high target == high $    ;No need to change PCLATH
> > >                 messg "CALLPAGE evaluated to simple call"
> > >         else
> > >                 if Wtemp == 0 ;Do not save and reload W, +2
> instructions
> > >                         movlw   high target
> > >                         movwf   PCLATH
> > >                 else ;Save and restore W using register adress Wtemp,
> +4
> > instr.

> > >                         movwf   Wtemp
> > >                         movlw   high target
> > >                         movwf   PCLATH
> > >                         movf    Wtemp,W
   1 data ram location used

> > >                 endif
> > >         endif
> > >         call target
> > >         endm

                    ;    W                   PCLATH
                    ;  Wval                  ???
 movwf  PCLATH      ;  Wval                  Wval
 xorlw  high target ;Wval XOR high target    Wval
 xorwf  PCLATH,f    ;Wval XOR high target    high target
 xorwf  PCLATH,w    ;  Wval                  high target

These 4 instructions made the same work but not use data ram.

--
/* Alexandr Redchuk     KILLspamReAlKILLspamspamreal.kiev.ua  */

1998\02\07@170347 by Morgan Olsson

picon face
>> > >                         movwf   Wtemp
>> > >                         movlw   high target
>> > >                         movwf   PCLATH
>> > >                         movf    Wtemp,W
>    1 data ram location used
-snip-
{Quote hidden}

Amazing...
Very nice, Alexander!

I will use your metod to move a literal to ram without changing W, although
I have spare ram, because it«s neat! Only thing to think about is it set Z
flag according to W.
I will make it a macro, so it is also understandable when overlooking the
program. (It do look very confusing to me)

BTW, as the assembler today don«t like code length changing macros, I
changed them to just send messages and warnings in the listing instead. So
I change manually, if needed.  Helps so I don«t forget to change page, or
don«t waste code and execution time.

The line in my macro
        if high target == high $
is appropriate if we are calling a table.

But if we are calling a routine we do not have to check more other bits
than is in PC but not in call instruction, so we mask them
       if (high target) && PCLATH_callmask == (high $) && PCLATH_callmask
Where PCLATH_callmask is depending on processor; b«00011000' for a 4-page
PIC16-series, specified in processor header file.

But for a two page device we only need to check one bit, and then only use
a bit manipulation to change PCLATH. And for 4 page it sometimes have
change two bits, sometimes one bit on PCLATH. I«m vorking on a macro...

But, there is a hole in this safety fence!
In the case the routine is placed on a page edge:
PCLATH was pointing to this routine at last call or goto (to this routine).
If the routine processing continues over the the edge to next page, and
then wants to call or goto to that page, then it must set the PCLATH even
though it now is on next page already! (And if it needs to jump to
beginning of itself it do not need to change PCLATH)

Or anyone have a neat idea there? (except writing in C)

The simple way to avoid problems is of course to place a routine so the
code execution do not fall over a page boundary.

I also use checking in TABLES: If high $ at first instruction after addwf
is different from high $ at last instruction, then it creates an error
message.

/Morgan

/  Morgan Olsson, MORGANS REGLERTEKNIK, SE-277 35 KIVIK, Sweden \
\  spamBeGonemrtspamBeGonespaminame.com, ph: +46 (0)414 70741; fax +46 (0)414 70331    /

1998\02\09@020844 by Alexandr A. Redchuck

flavicon
face
Hi,Morgan Olsson!
7-Feb-98 22:53 you wrote about "Re: Automatic call optimization macro"

> >  movwf  PCLATH      ;  Wval                  Wval
> >  xorlw  high target ;Wval XOR high target    Wval
> >  xorwf  PCLATH,f    ;Wval XOR high target    high target
> >  xorwf  PCLATH,w    ;  Wval                  high target
> >
> >These 4 instructions made the same work but not use data ram.
> >
> >/* Alexandr Redchuk     TakeThisOuTReAlEraseMEspamspam_OUTreal.kiev.ua  */

> I will use your metod to move a literal to ram without changing W, although
> I have spare ram, because it's neat! Only thing to think about is it set Z
> flag according to W.
> I will make it a macro, so it is also understandable when overlooking the
> program. (It do look very confusing to me)

Yes, but
>> > >                         movf    Wtemp,W
in first variant change Z too.
And
 movwf dst
 addlw -literal
 subwf dst,f
 addwf dst,f
change even C.

More important is that destination (PCLATH in example above) is
writed twice (and first time with dirty from its point of view).

Don't use your macro with ports, TRIS registers and "volatile"
SFRs (like SSP/I2C transmit register).

XORWF is very useful instruction. Another nice code sequence is
'exchange and bit compare':
 ; W     contain new value (f.e. state of 8 buttons)
 xorwf  oldstate,w
 xorwf  oldstate,f
 ; oldstate   contain new value, W = 1 in changed bits

Simply put 'andlw mask' between above two commands, and the same
job will be done with bit field

InsBitsW macro dst,mask
;; W    = new value of bit field (shifted to its place)
;; mask = field mask (f.e. B'00011100')
   xorwf   dst,w
   andlw   mask
   xorwf   dst,f
;; dst = (dst AND NOT mask) OR (w AND mask)
;; W   = (w XOR dst) AND mask
  endm

Excuse me if I tell common truth.

> But if we are calling a routine we do not have to check more other bits
> than is in PC but not in call instruction, so we mask them
>         if (high target) && PCLATH_callmask == (high $) && PCLATH_callmask
-snip-
> But, there is a hole in this safety fence!
> In the case the routine is placed on a page edge:
> PCLATH was pointing to this routine at last call or goto (to this routine).
> If the routine processing continues over the the edge to next page, and
> then wants to call or goto to that page, then it must set the PCLATH even
> though it now is on next page already! (And if it needs to jump to
> beginning of itself it do not need to change PCLATH)

Oh-oh-oh!

> The simple way to avoid problems is of course to place all routine so the
> code execution do not fall over a page boundary.
I prefer this.

But You may (NO GUARANTEES! :-) try to track PCLATH.

CODE_PAGE  -- compilation time variable, value of PCLATH,{3,4}

Change PCLATH only with special macro which set CODE_PAGE to
appropriate value. Use the macro at subroutine start (PCLATH,{3,4}
always correspond with $ at this point) and within LCALL/LGOTO macros.

LCALL/LGOTO macro can check CODE_PAGE and change PCLATH if
current $ not correspond to it. Redundant PCLATH changing may be
eliminated in code:
       movf    var1,w
       LCALL subr
       movf    var2,w
       LCALL subr
But this code may behave erroneously when 'subr' change PCLATH
too. For each of such subroutnies You must make another macros
which set CODE_PAGE to special value CODE_PAGE_UNKNOWN (force
following LCALL/LGOTO to set PCLATH unconditionally) after
subroutine call. And more, and more...

So I prefer:
> The simple way to avoid problems is of course to place all routine so the
> code execution do not fall over a page boundary.

> I also use checking in TABLES: If high $ at first instruction after addwf
> is different from high $ at last instruction, then it creates an error
> message.
In my opinion this work must make LINKER !!! For example
  defseg tbl1,class=code,bound=100h
  seg tbl1
table1:
  addwf PCL,f
  ...

and let linker think about place for table...
But I don't know such package (assembler+linker) for PIC.


;----------------------------------------
; Sorry, I am weak in English and PASCAL.
;----------------------------------------

/* Alexandr Redchuk     RemoveMEReAlspamTakeThisOuTreal.kiev.ua  */
/* Kiev, Ukraine                           */

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