> From: Dwayne Reid > > HELP! > > I've just gone over the 2K boundary on my '73 project and am looking for > easier ways of dealing with the page bits. I started off with Steve Hardy's > code from a few weeks ago, as follows: > > ; Expands to 1 or 3 instructions, depending on whether cross-block call. > perform macro routine > if (routine & 0x800) != ($ & 0x800) > if (routine & 0x800) > [optionally disable interrupts] > bsf pclath,3 > else > bcf pclath,3 > endif > call routine > if ($ & 0x800) > bsf pclath,3 > else > bcf pclath,3 > [optionaly enable interrupts] > endif > else NOP <--------- try inserting this NOP [optional nops for interrupt] [issue warning to convert to normal call] > call routine > endif > endm > > However, I get what appears to be assembler phasing errors because the > instruction added to modify PCLATH moves the rest of the code by 1 byte on > the second pass of the assembler. So: I did it the "manual" way, as follows: Mea culpa! Yes, the perennial phase error. Well, if the assembler is not smart enough to handle this (and not many of them are) then insert two NOPs before the unadorned CALL. This makes the macro generate the same number of instructions no matter which 'if' condition hits. Naturally, this is a waste of time and space so you can add a warning to this saying something like 'redundant NOPs added!' and then go and manually change to a normal call when your code is fairly well debugged. I encountered this sort of problem when writing a Z80 assembler. The Z80 has two different flavours of branch: JR and JP. JR only had a short range (and takes 2 bytes) whereas JP could jump anywhere (3 byte instruction). I wanted to implement a pseudo-op called 'J' which used the shortest possible opcode JR or JP. It turned out that to optimally implement this, the assembler would potentially have to make a large number of passes, refining its estimate of the value of each label each time. It is also conceivable that the assembler could get stuck in an infinite loop. > > xcall MACRO routine ;flip page bit > if ($ & 0x800) > bcf PCLATH,3 > else > bsf PCLATH,3 > endif > call routine > if ($ & 0x800) > bsf PCLATH,3 > else > bcf PCLATH,3 > endif > endm > > In this case, I simply looked at the my listing to see where the assembler > warned that I was crossing the page boundary, then replaced those calls with > xcalls. So far, so good. Now what I would like is some way for the macro > to not allow the assembler to generate the "crossing page boundary" warning > where I have already used xcall. I suppose that I could try turning the > message off, then back on before and after the actual call, but I was hoping > that someone else has a better way. > > I recall that Andy Warren had some macros written for the '57 where he used > DATA statements to synthesize the appropriate commands. I'm going to look > for those messages again and see if I can modify the macros to work on the > '73. Andy - have you already done that; if so, can I use them in my > [commercial] project? No matter what you do, if the macro expands to different lengths depending on a forward reference then you will encounter the same problem. I would suggest selective suppression of the warning message if the assembler can handle it. If you were brave, you could write an assembler driver which could do the following: call assembler for first trial (issuing redundant NOPs). examine the assembler error listing, looking for redundant NOP warnings. copy and modify the source, changing macro to plain call where flagged. assemble the modified source. examine for errors and tell user if still got errors. Kludge to the max! Regards, SJH Canberra, Australia