On another subject

Discuss the Integrated Development Environment (IDE)

Moderators: David Barker, Jerry Messina

Post Reply
Richard Bowser
Posts: 2
Joined: Mon Oct 30, 2006 10:45 pm

On another subject

Post by Richard Bowser » Thu Jan 04, 2007 6:25 pm

Among the features I find most attractive in Swordfish is its flexibility in byte addressing of longword (32-bit) data. For example, I frequently rely on constructs such as defining variables “Private Dim CSst As LongWord” and then setting aliases like “Dim TbstL As CSst.Byte0 “, “Dim TbstH As CSst.Byte1”, and “Dim TbsvU As CSst.Byte2”. I find this extremely useful in porting code from PBP to Swordfish, as in writing a program memory checksum calculator.

However, I was frustrated when I discovered the compiler does not support similar addressing for constants. What I would like to do is define a constant “Private Const CSst As LongWord = $000018 //start of pgm memory” and then use similar aliases for the individual bytes that make up the longword constant. I realize that putting in runtime support for such variable aliasing must have been an arduous task. However, byte addressing of longword constants would require no runtime support whatsoever. All the code generator would need to do is pick off one particular byte of an already known constant. Would it be feasible to support such operations in a future edition of the compiler?
:idea:

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Thu Jan 04, 2007 6:59 pm

> Would it be feasible to support such operations in a
> future edition of the compiler?

Bytes, Words, LongWords etc are actually represented internally in the compiler as special case structures - which supports the dot notation used. This makes it possible to support declarations such as...

Code: Select all

dim MyLong as longword
dim MyByteA as MyLong.Word1.Byte1
dim MyBytesB as MyLong.Words(1).Bytes(1)
or you can use directly in your code...

Code: Select all

MyLong.Words(1).Bytes(1) = 10
MyLong.Word1.Byte1 = 10

Unfortunately, constants are not represented this way. The effort needed to implement would, in my opinion, not be worth the time. However, you can do what you want like this...

Code: Select all

include "usart.bas"
include "convert.bas"

const
   CSst as longword = $12345678,
   CSstL as byte = CSst,
   CSstH as byte = CSst >> 8,
   CSstHH as byte = CSst >> 16,
   CSstHHH as byte = CSst >> 24

SetBaudrate(br19200)
Write("$", HexToStr(CSstL), 13, 10)
Write("$", HexToStr(CSstH), 13, 10)
Write("$", HexToStr(CSstHH), 13, 10)
Write("$", HexToStr(CSstHHH), 13, 10)

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Thu Jan 04, 2007 8:46 pm

Dave,

Is there a method to write a particular value anywhere in Program Mem? For instance, can I get the compiler to write the value for RETURN at $3FFE?

Code: Select all

Const RTRN as Word = 0x0012 Org 0x3FFE
Or maybe this was what you were trying to explain above.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Thu Jan 04, 2007 10:12 pm

> Is there a method to write a particular value anywhere
> in Program Mem

At the moment, you cannot ORG in Swordfish. Atomic constants types are actually embedded in program memory when they are needed. For example,

Code: Select all

const RTRN as word = $0012
dim Value as word
Value = RTRN
will translate to...

Code: Select all

     CLRF M0_U16H,0
     MOVLW 18
     MOVWF M0_U16,0
Array constants are stored differently in ROM (using DB). You can obviously index a constant array like any other type of array in swordfish, or you can get the ROM address to manipulate directly (for example, @MyConstArray)

If you want to use jump tables, you can use something like this...

Code: Select all

  
noinline function Jump(pOffset as WREG) as WREG
   pOffset = pOffset * 2
   PCL = PCL + pOffset
   asm
      retlw 0x02 ; offset = 0
      retlw 0x04 ; offset = 1
      retlw 0x08 ; offset = 2
      retlw 0x0A ; offset = 3
   end asm   
end function   

dim Value as byte
Value = Jump(3)
Note that for PIC18, ROM access is BYTES but word aligned, hence the * 2 multiply. If you index word aligned (0,2,4,8 etc) you wont need the multiply.

The ASM generated in the above example is pretty efficient, as the param and return is in WREG.

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Fri Jan 05, 2007 12:29 am

Thanks Dave. Those types of explanations are so helpful.

This is a silly optimization idea and why I asked the question, for which I don't know if there is really a practical solution. If, for instance, you could insert the RETURN Instruction ($0012) at the end of Program ROM, you could probably make CALL's to any of the empty memory addreses before this point and then let the Program Counter NOP it's way to this inserted Return instruction. It could be a very optimized method of creating simple and short delays with unused Program Memory by a CALL to an address as many memory positions as requred for the short delay.

Post Reply