gnupic: Trouble with macros conditionally generating code
Subject:
Re: Trouble with macros conditionally generating code
From:
Craig Franklin ####@####.####
Date:
20 Nov 2004 03:51:30 +0000
Message-Id: <419E6B7B.4060607@users.sourceforge.net>
Pete Elmore wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> I'm having some difficulty with a macro I wrote. Basically, I wanted
> something simple to transparently call across page boundaries without
> corrupting W.
The manual is wrong. So is the mpasm manual. W is only modified with
17xx devices.
> This looked relatively simple; according to page 32 of
> the spec sheet for the chip I'm using (the PIC 16F877), when doing a
> call or goto, only bits 3 and 4 of PCLATH are loaded into the PC, and
> the rest come from the instruction itself. So, I thought that I could
> perform a simple test to see if we were crossing a page boundary, and if
> so, to just use bsf and bcf to set/clear the appropriate bits. I came
> up with the following:
>
> fcall macro label
> if ((high(label) & 0x18) != (high($) & 0x18))
> if((high(label) & 8) == 8)
> bsf 0xa, 3
> else
> bcf 0xa, 3
> endif
> if((high(label) & 0x10) == 0x10)
> bsf 0xa, 4
> else
> bcf 0xa, 4
> endif
> endif
> call label
> endm
>
> However, if I attempt to use the macro, I get errors like the following:
>
> menu.s:1:Error [116] Value of symbol "main_menu" differs on second pass
> ~ pass 1=1719, pass 2=1721
>
Here is your code assembled with mpasm:
MPASM 03.80.04 Internal TEMP.ASM
11-19-2004 21:46:04 PAGE 1
LOC OBJECT CODE LINE SOURCE TEXT
VALUE
00001 processor 16f877
00002
00003 fcall macro label
00004 if ((high(label) & 0x18) != (high($) &
0x18))
00005 if((high(label) & 8) == 8)
00006 bsf 0xa, 3
00007 else
00008 bcf 0xa, 3
00009 endif
00010 if((high(label) & 0x10) == 0x10)
00011 bsf 0xa, 4
00012 else
00013 bcf 0xa, 4
00014 endif
00015 endif
00016 call label
00017 endm
00018
00019
0000 00020 org 0
00021
00022 fcall main
M if ((high(main) & 0x18) != (high($) &
0x18))
M if((high(main) & 8) == 8)
M bsf 0xa, 3
M else
0000 118A M bcf 0xa, 3
M endif
M if((high(main) & 0x10) == 0x10)
0001 160A M bsf 0xa, 4
M else
M bcf 0xa, 4
M endif
M endif
Message[306]: Crossing page boundary -- ensure page bits are set.
0002 2000 M call main
Error[116] : Address label duplicated or different in second pass (temp)
0003 00023 temp:
00024
1000 00025 org 1000
1000 00026 main:
00027 end
> This error is repeated for every label in every file below the use of
> the macro, with the pass 2 address being the same as the pass 1 address
> plus two. The errors were a little less than helpful, but I narrowed it
> down to the macro. It seems to stem from the fact that the macro
> generates code that is a different size depending on the location of
> labels. That the following code works seems to confirm this theory:
>
> fcall macro label
> if ((high(label) & 0x18) != (high($) & 0x18))
> if((high(label) & 8) == 8)
> bsf 0xa, 3
> else
> bcf 0xa, 3
> endif
> if((high(label) & 0x10) == 0x10)
> bsf 0xa, 4
> else
> bcf 0xa, 4
> endif
> else
> nop
> nop
> endif
> call label
> endm
>
> Note the additional nops. They ensure that the macro always generates
> three instructions, rather than sometimes generating three and sometimes
> generating one. Although I acknowledge the possibility that my code is
> broken in some way, I am fairly certain that this is a bug in the
> assembler.
>
In my example, main has a value of 0 on the first pass, 1000 on the
second. So the number of instructions changes. The nops fix the number
of instructions.
> I'm using Debian at work, so that might be relevant if Debian's version
> of gpasm is broken.
>
> pete@bob:~/sr1$ uname -a
> Linux bob 2.6.8-1-k7 #1 Mon Sep 13 23:56:00 EDT 2004 i686 GNU/Linux
> pete@bob:~/sr1$ gpasm -v
> gpasm-0.12.3 beta
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.2.5 (GNU/Linux)
> Comment: Using GnuPG with Debian - http://enigmail.mozdev.org
>
> iD8DBQFBnaxUv24lB609Ih8RAmLfAKDHAsNWHDcXw5g+s9LPpbMysNC11ACfT1pE
> EcINdGAib8g/RBBRw0admYU=
> =QFFp
> -----END PGP SIGNATURE-----
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ####@####.####
> For additional commands, e-mail: ####@####.####
>
>