Chip,
I've spent considerable time trying to compile my monitor code into hub so that it can be used by everyone from spin and pasm.
But, because I cannot call the current ROM monitor from spin, I am flying blind to see what in the hell is going wrong. I coded the ROM monitor so that all programs could call it to get going.
So, since you are not willing to compromise, Can you build me a version of pnut that keeps $1E0-$1E0 free so that I can use the monitor to debug my replacement code? I can then build a loadable hub version that all can incorporate as an object.
Cluso99, is there a reason you can't make your monitor use $120..$12F, or anything below? I don't think it will be very simple for me to do what you're asking. I'd have to make a lot of edits to my tools and there are probably some gotcha's lurking in the effort. Your monitor has free use of $000..$131.
Chip,
I am really trying!
To change the parameters to use $120-$12F instead of $1E0-$1EF is easy, and I can compile it easily too using the original pnut v32i.
BUT, trying to compile it and call it using pnut v34R is impossible. First up, it ignores the ORGH $anywhere. I don't know (or have any confidence) that it compiled correctly. It certainly cannot be called from where is it located, since it ignores the ORGH $FCxxx and places it at hub $0 upwards which if course cannot be called in hubexec.
I am just trying to work within stupid constraints. Surely, pnut should honor an ORGH $XXX.
I have even considered creating the binary blob using pnut v32i (or fastspin) and then trying to load it within pnut v34R but I have no confidence in whether this will work or not. How the devil do you expect anyone to write hubexec code when they have no idea where it gets loaded into???
It's not a simple matter of using relative code since there are many entry points into the hubexec code block. It was written this way because we did not have ROM space to put a table at the beginning.
Currently, I feel that absolutely everything I've ever done on P1, and P2, is no longer usable. I am not willing to start over again. If I do that it certainly will not be on a P2.
Chip,
I've spent considerable time trying to compile my monitor code into hub so that it can be used by everyone from spin and pasm.
But, because I cannot call the current ROM monitor from spin, I am flying blind to see what in the hell is going wrong. I coded the ROM monitor so that all programs could call it to get going.
So, since you are not willing to compromise, Can you build me a version of pnut that keeps $1E0-$1E0 free so that I can use the monitor to debug my replacement code? I can then build a loadable hub version that all can incorporate as an object.
Cluso99, is there a reason you can't make your monitor use $120..$12F, or anything below? I don't think it will be very simple for me to do what you're asking. I'd have to make a lot of edits to my tools and there are probably some gotcha's lurking in the effort. Your monitor has free use of $000..$131.
Chip,
I am really trying!
To change the parameters to use $120-$12F instead of $1E0-$1EF is easy, and I can compile it easily too using the original pnut v32i.
BUT, trying to compile it and call it using pnut v34R is impossible. First up, it ignores the ORGH $anywhere. I don't know (or have any confidence) that it compiled correctly. It certainly cannot be called from where is it located, since it ignores the ORGH $FCxxx and places it at hub $0 upwards which if course cannot be called in hubexec.
I am just trying to work within stupid constraints. Surely, pnut should honor an ORGH $XXX.
I have even considered creating the binary blob using pnut v32i (or fastspin) and then trying to load it within pnut v34R but I have no confidence in whether this will work or not. How the devil do you expect anyone to write hubexec code when they have no idea where it gets loaded into???
It's not a simple matter of using relative code since there are many entry points into the hubexec code block. It was written this way because we did not have ROM space to put a table at the beginning.
You could use ORGH $FC000 and then BYTEMOVE($FC000,@monitor, $4000). That way, it was compiled with the address that you want, so you can move it to where you want it to be.
This starts your rom monitor in a new cog (after a short delay to start the terminal):
_clkfreq = 160_000_000
PUB Start() | x
waitms(1500)
x := (clkfreq / 115200) << 16 + 7
coginit(16, @init_cog, x) 'start rom-monitor in a new cog
repeat
DAT
org 0
init_cog
mov $1E0,ptra 'lmm_x = baudrate+bits
call #\$FCAB8 'serial_init
mov $1EF,##$FC000 'buffer addr
jmp #\$FCD78 'start monitor
Spin code certainly knows the hubadresses at runtime, it's just the PASM code that has not the right (absolute) addresses. But there is a constant offset to the absolute address. You should be able to use a longmove($4000,@hubcode,codesize) to move it at the position you want it to have, and then start it there.
Chip,
I've spent considerable time trying to compile my monitor code into hub so that it can be used by everyone from spin and pasm.
But, because I cannot call the current ROM monitor from spin, I am flying blind to see what in the hell is going wrong. I coded the ROM monitor so that all programs could call it to get going.
So, since you are not willing to compromise, Can you build me a version of pnut that keeps $1E0-$1E0 free so that I can use the monitor to debug my replacement code? I can then build a loadable hub version that all can incorporate as an object.
Cluso99, is there a reason you can't make your monitor use $120..$12F, or anything below? I don't think it will be very simple for me to do what you're asking. I'd have to make a lot of edits to my tools and there are probably some gotcha's lurking in the effort. Your monitor has free use of $000..$131.
Chip,
I am really trying!
To change the parameters to use $120-$12F instead of $1E0-$1EF is easy, and I can compile it easily too using the original pnut v32i.
BUT, trying to compile it and call it using pnut v34R is impossible. First up, it ignores the ORGH $anywhere. I don't know (or have any confidence) that it compiled correctly. It certainly cannot be called from where is it located, since it ignores the ORGH $FCxxx and places it at hub $0 upwards which if course cannot be called in hubexec.
I am just trying to work within stupid constraints. Surely, pnut should honor an ORGH $XXX.
I have even considered creating the binary blob using pnut v32i (or fastspin) and then trying to load it within pnut v34R but I have no confidence in whether this will work or not. How the devil do you expect anyone to write hubexec code when they have no idea where it gets loaded into???
It's not a simple matter of using relative code since there are many entry points into the hubexec code block. It was written this way because we did not have ROM space to put a table at the beginning.
You could use ORGH $FC000 and then BYTEMOVE($FC000,@monitor, $4000). That way, it was compiled with the address that you want, so you can move it to where you want it to be.
Attached is my current FemtoBasic version for P2. FemtoDongle2.spin (and SmartSerial.spin) compile with FastSpin on a Mac and the compiled binary seems to work. The "Used_With_PNut" folder has modified versions of the two source files. FemtoDongle2.spin2 mostly has "()" added in the declarations of parameterless methods. SmartSerial.spin2 is the problem. PNut doesn't recognize the method calls like "wxpin_", but does accept "wxpin". It doesn't recognize "dirh_" nor "dirh" or "_dirh". This may just be an incompatibility between FastSpin and PNut, but it's confusing me.
Here is a Serial object, that works for PNUT and Fastspin. It's already named according your use
There is a testcode at begin which you can comment out to spare some bytes.
Attached is my current FemtoBasic version for P2. FemtoDongle2.spin (and SmartSerial.spin) compile with FastSpin on a Mac and the compiled binary seems to work. The "Used_With_PNut" folder has modified versions of the two source files. FemtoDongle2.spin2 mostly has "()" added in the declarations of parameterless methods. SmartSerial.spin2 is the problem. PNut doesn't recognize the method calls like "wxpin_", but does accept "wxpin". It doesn't recognize "dirh_" nor "dirh" or "_dirh". This may just be an incompatibility between FastSpin and PNut, but it's confusing me.
Mike, I made lots of minor edits to your code and it is compiling now. Not sure if it works, though.
These were the edits, in order of frequency:
1) Adding "()" after method names
2) Adding " : result " after method declarations where necessary
3) Changing "=<" or "=>" to "<=" or ">="
4) Changing "|<" to "decod"
The compiled size is 7,096 bytes, plus 4,088 bytes for the interpreter.
Chip,
Am I correct that no code can be compiled for hubexec unless it it moved to the address it is designed to run at?
For example, if I have a piece of pasm code and I ORGH it with or without any address, I still must do a bytemove(dest, srce, len)?
Because it seems that the code is placed in hub starting at $0 which of course is below $400 and therefore cannot be run as hubexec.
No, of course hubexec code can run where it sits. You just have to make it relatively-addressed and get the address to the start of it. I posted some examples of how to do this, but you seemed to want to run your code at a fixed address, so I suggested you just move it to where you want to run it, since you were not supporting relocation.
Thanks Chip.
Somewhere I have problems with my code not working as it should, but it's like looking for a needle in a haystack.
I ended up making a really simple program (posted on the Spin2 Snippets thread) to flash an LED in hubexec code. Now I can proceed forward again.
BTW What I need is for resident code to remain in hub between loading/running programs from SD. These programs will use CON Equates for the entry points into the pre-loaded resident code. The resident code will provide SD FAT32 file routines, Input/Output routines via a mailbox so that the actual I/O can be redirected to serial or to keyboard/screen. This is the basis of an OS which I did for the P1 many moons ago. I am trying to port this to the P2. This is why it is essential that I know where the code is located in hub.
Anyway, with what I have now, I can place my code where I require it to be within hub. It is a shame that the ROM Monitor cannot be used as-is but I will reload it with new register usage.
Chip,
Here is my contrived example of calling hubexec residing in its' own OBJ module.
Can you tell me how to call the routine _HubToggle in the OBJ module?
Rather than having to declare _clkfreq and LED_p2eval again in the OBJ module, how do I declare them in the top module?
CON
_clkfreq = 297_000_000 'set clock frequency
LED_p2eval = 56 ' P2EVAL Blue LED 0=ON
OBJ
ob : "Test-OBJ-12i"
PUB go()
repeat
PR0 := 10
CALL(@ob._HubToggle) ' call Toggle LED
WAITMS(4000) ' 4s
and the OBJ
CON
_clkfreq = 297_000_000 'set clock frequency
LED_p2eval = 56 ' P2EVAL Blue LED 0=ON
PUB dummy()
DAT
orgh
_hubToggle
' mov PR0,#10 ' spin pasm comms registers
.loop drvnot #LED_p2eval ' flash P2EVAL blue led
waitx ##_clkfreq/2 ' 0.5s
djnz PR0,#.loop
RET ' return
Cluso, like Ozpropdev showed, you need to make a method to return the address of the PASM code:
ClusoTop.spin2
CON
_clkfreq = 297_000_000 'set clock frequency
LED_p2eval = 56 'P2EVAL Blue LED 0=ON
OBJ
ob : "ClusoObj"
PUB go()
repeat
PR0 := 10
CALL(ob.HubToggle()) 'call Toggle LED
WAITMS(4000) '4s
ClusoObj.spin2
CON
_clkfreq = 297_000_000 'set clock frequency
LED_p2eval = 56 'P2EVAL Blue LED 0=ON
PUB HubToggle() : x
return @_HubToggle
DAT
orgh
_HubToggle
.loop drvnot #LED_p2eval ' flash P2EVAL blue led
waitx ##_clkfreq/2 ' 0.5s
_ret_ djnz PR0,#.loop
Cluso, like Ozpropdev showed, you need to make a method to return the address of the PASM code:
ClusoTop.spin2
CON
_clkfreq = 297_000_000 'set clock frequency
LED_p2eval = 56 'P2EVAL Blue LED 0=ON
OBJ
ob : "ClusoObj"
PUB go()
repeat
PR0 := 10
CALL(ob.HubToggle()) 'call Toggle LED
WAITMS(4000) '4s
ClusoObj.spin2
CON
_clkfreq = 297_000_000 'set clock frequency
LED_p2eval = 56 'P2EVAL Blue LED 0=ON
PUB HubToggle() : x
return @_HubToggle
DAT
orgh
_HubToggle
.loop drvnot #LED_p2eval ' flash P2EVAL blue led
waitx ##_clkfreq/2 ' 0.5s
_ret_ djnz PR0,#.loop
So what do I do when I have 25+ entry points? Surely I don;t need a method for every entry point?
This is why we have "bloat" code on the PC. Are we now getting it on the P2 too???
At least I can still compile a PASM only program with both pnut v34R and Fastspin. Both give me a listing sufficient to work out the fixed hub addresses. I just have to work out how to include the code into spin so I can move it to where I want it. Not easy tho
@Cluso99: I wonder if it might be simpler to store jump vectors at a specific memory memory area somewhat like what was done with the 8080/Z80 for CPM.
Today I took the Spin2 compiler, which is 13,600 lines of 80386 assembly, and converted the 2,270 lines containing all the equates and automatic symbols into Spin2 source. It's all data, no code, and compiles to 11KB. I want to get the parser working in Spin2, but I need all this data present for context. Here is the Spin2 source for this, so far.
I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
byte "X_DDS_GOERTZEL_SINC1",0, type_con, long $F007 << 16
Today I took the Spin2 compiler, which is 13,600 lines of 80386 assembly, and converted the 2,270 lines containing all the equates and automatic symbols into Spin2 source. It's all data, no code, and compiles to 11KB. I want to get the parser working in Spin2, but I need all this data present for context. Here is the Spin2 source for this, so far.
I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
byte "X_DDS_GOERTZEL_SINC1",0, type_con, long $F007 << 16
Nice! It sounds like you're well on the way to a self-hosting compiler. I assume that is your goal.
Today I took the Spin2 compiler, which is 13,600 lines of 80386 assembly, and converted the 2,270 lines containing all the equates and automatic symbols into Spin2 source. It's all data, no code, and compiles to 11KB. I want to get the parser working in Spin2, but I need all this data present for context. Here is the Spin2 source for this, so far.
I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
byte "X_DDS_GOERTZEL_SINC1",0, type_con, long $F007 << 16
Nice! It sounds like you're well on the way to a self-hosting compiler. I assume that is your goal.
Yes, but also as a replacement for the '386 code. I realized the other day that there is a contiguous group of bytecodes that are P2-hardware-specific, while the rest are hardware-agnostic. This means that only a basic bytecode interpreter is needed on any system to run non-hardware Spin2 code, like a compiler. I want to go down this road and get a feel for how fast and efficient this approach might be.
Today I took the Spin2 compiler, which is 13,600 lines of 80386 assembly, and converted the 2,270 lines containing all the equates and automatic symbols into Spin2 source. It's all data, no code, and compiles to 11KB. I want to get the parser working in Spin2, but I need all this data present for context. Here is the Spin2 source for this, so far.
I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
byte "X_DDS_GOERTZEL_SINC1",0, type_con, long $F007 << 16
Nice! It sounds like you're well on the way to a self-hosting compiler. I assume that is your goal.
Yes, but also as a replacement for the '386 code. I realized the other day that there is a contiguous group of bytecodes that are P2-hardware-specific, while the rest are hardware-agnostic. This means that only a basic bytecode interpreter is needed on any system to run non-hardware Spin2 code, like a compiler. I want to go down this road and get a feel for how fast and efficient this approach might be.
That sounds like a good plan. I'm looking forward to seeing the results.
That sounds like a good plan. I'm looking forward to seeing the results.
To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.
That sounds like a good plan. I'm looking forward to seeing the results.
To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.
Symbol tables are the first thing to code, then the parser, since it needs symbols.
Yes, this should shake out any bugs and provide impetus for improvements.
That sounds like a good plan. I'm looking forward to seeing the results.
To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.
Symbol tables are the first thing to code, then the parser, since it needs symbols.
Yes, this should shake out any bugs and provide impetus for improvements.
How do you plan to implement the Spin2 byte code interpreter to run on the PC? You might want to consider writing it in C so it can be ported to non-Windows systems easily.
That sounds like a good plan. I'm looking forward to seeing the results.
To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.
Symbol tables are the first thing to code, then the parser, since it needs symbols.
Yes, this should shake out any bugs and provide impetus for improvements.
How do you plan to implement the Spin2 byte code interpreter to run on the PC? You might want to consider writing it in C so it can be ported to non-Windows systems easily.
It's going to be a short program, so it can be written in anything that works.
That sounds like a good plan. I'm looking forward to seeing the results.
To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.
Symbol tables are the first thing to code, then the parser, since it needs symbols.
Yes, this should shake out any bugs and provide impetus for improvements.
How do you plan to implement the Spin2 byte code interpreter to run on the PC? You might want to consider writing it in C so it can be ported to non-Windows systems easily.
It's going to be a short program, so it can be written in anything that works.
I know you've posted the source code for the P2 byte code interpreter but do you have a document describing them?
This is an interesting development and I am hoping things work out well Chip. This is really called taking your own medicine now isn't it.
I wonder how well Spin2 will deal with file parsing / string manipulation aspects of a compiler implementation. You'll want to develop some handy utility functions there I imagine. Being able to run Spin2 code on a non-P2 would be interesting too.
This is an interesting development and I am hoping things work out well Chip. This is really called taking your own medicine now isn't it.
I wonder how well Spin2 will deal with file parsing / string manipulation aspects of a compiler implementation. You'll want to develop some handy utility functions there I imagine. Being able to run Spin2 code on a non-P2 would be interesting too.
You can already use Eric's spin2cpp to translate Spin2 to C and then compile it with a PC C compiler.
Chip, With PNutVr I'm getting an error with a call to AKPIN (Expression terms must return a single result). Your documentation of this call doesn't seem to imply that there is more than one result.
Comments
I am really trying!
To change the parameters to use $120-$12F instead of $1E0-$1EF is easy, and I can compile it easily too using the original pnut v32i.
BUT, trying to compile it and call it using pnut v34R is impossible. First up, it ignores the ORGH $anywhere. I don't know (or have any confidence) that it compiled correctly. It certainly cannot be called from where is it located, since it ignores the ORGH $FCxxx and places it at hub $0 upwards which if course cannot be called in hubexec.
I am just trying to work within stupid constraints. Surely, pnut should honor an ORGH $XXX.
I have even considered creating the binary blob using pnut v32i (or fastspin) and then trying to load it within pnut v34R but I have no confidence in whether this will work or not. How the devil do you expect anyone to write hubexec code when they have no idea where it gets loaded into???
It's not a simple matter of using relative code since there are many entry points into the hubexec code block. It was written this way because we did not have ROM space to put a table at the beginning.
Currently, I feel that absolutely everything I've ever done on P1, and P2, is no longer usable. I am not willing to start over again. If I do that it certainly will not be on a P2.
You could use ORGH $FC000 and then BYTEMOVE($FC000,@monitor, $4000). That way, it was compiled with the address that you want, so you can move it to where you want it to be.
This starts your rom monitor in a new cog (after a short delay to start the terminal):
Spin code certainly knows the hubadresses at runtime, it's just the PASM code that has not the right (absolute) addresses. But there is a constant offset to the absolute address. You should be able to use a longmove($4000,@hubcode,codesize) to move it at the position you want it to have, and then start it there.
Andy
OK, I'll give this a try tonight.
Am I correct that no code can be compiled for hubexec unless it it moved to the address it is designed to run at?
For example, if I have a piece of pasm code and I ORGH it with or without any address, I still must do a bytemove(dest, srce, len)?
Because it seems that the code is placed in hub starting at $0 which of course is below $400 and therefore cannot be run as hubexec.
Here is a Serial object, that works for PNUT and Fastspin. It's already named according your use
There is a testcode at begin which you can comment out to spare some bytes.
Andy
Mike, I made lots of minor edits to your code and it is compiling now. Not sure if it works, though.
These were the edits, in order of frequency:
1) Adding "()" after method names
2) Adding " : result " after method declarations where necessary
3) Changing "=<" or "=>" to "<=" or ">="
4) Changing "|<" to "decod"
The compiled size is 7,096 bytes, plus 4,088 bytes for the interpreter.
Here are the two files...
No, of course hubexec code can run where it sits. You just have to make it relatively-addressed and get the address to the start of it. I posted some examples of how to do this, but you seemed to want to run your code at a fixed address, so I suggested you just move it to where you want to run it, since you were not supporting relocation.
Somewhere I have problems with my code not working as it should, but it's like looking for a needle in a haystack.
I ended up making a really simple program (posted on the Spin2 Snippets thread) to flash an LED in hubexec code. Now I can proceed forward again.
BTW What I need is for resident code to remain in hub between loading/running programs from SD. These programs will use CON Equates for the entry points into the pre-loaded resident code. The resident code will provide SD FAT32 file routines, Input/Output routines via a mailbox so that the actual I/O can be redirected to serial or to keyboard/screen. This is the basis of an OS which I did for the P1 many moons ago. I am trying to port this to the P2. This is why it is essential that I know where the code is located in hub.
Anyway, with what I have now, I can place my code where I require it to be within hub. It is a shame that the ROM Monitor cannot be used as-is but I will reload it with new register usage.
Here is my contrived example of calling hubexec residing in its' own OBJ module.
Can you tell me how to call the routine _HubToggle in the OBJ module?
Rather than having to declare _clkfreq and LED_p2eval again in the OBJ module, how do I declare them in the top module? and the OBJ
Try this
Use a obj as a common header file config.spin2
ClusoTop.spin2
ClusoObj.spin2
So what do I do when I have 25+ entry points? Surely I don;t need a method for every entry point?
This is why we have "bloat" code on the PC. Are we now getting it on the P2 too???
At least I can still compile a PASM only program with both pnut v34R and Fastspin. Both give me a listing sufficient to work out the fixed hub addresses. I just have to work out how to include the code into spin so I can move it to where I want it. Not easy tho
This is maybe necessary if you don't have the routines in the same file.
If the routines are in the same file, you can just CALL them:
I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
Yes, but also as a replacement for the '386 code. I realized the other day that there is a contiguous group of bytecodes that are P2-hardware-specific, while the rest are hardware-agnostic. This means that only a basic bytecode interpreter is needed on any system to run non-hardware Spin2 code, like a compiler. I want to go down this road and get a feel for how fast and efficient this approach might be.
Symbol tables are the first thing to code, then the parser, since it needs symbols.
Yes, this should shake out any bugs and provide impetus for improvements.
It's going to be a short program, so it can be written in anything that works.
I wonder how well Spin2 will deal with file parsing / string manipulation aspects of a compiler implementation. You'll want to develop some handy utility functions there I imagine. Being able to run Spin2 code on a non-P2 would be interesting too.