Detailed Listing from OpenSpin
Memotech_Bill
Posts: 14
in Propeller 1
Like a number of people before me, I found myself in need of understanding where my Propeller code is located in memory. However, I seem to have taken a different approach to the problem. Instead of disassembling the generated binary, I have instrumented the OpenSpin compiler.
This has the disadvantage that it can only be applied to code assembled with OpenSpin.
Conversely, it enables the listing to refer directly to the source code. An abbreviated example output is given below.
My additions to OpenSpin can be found at: https://github.com/Memotech-Bill/OpenSpin
The code probably needs further testing, but it does everything that I want, and I can go back to trying to work out what is wrong with my Propeller code.
This has the disadvantage that it can only be applied to code assembled with OpenSpin.
Conversely, it enables the listing to refer directly to the source code. An abbreviated example output is given below.
My additions to OpenSpin can be found at: https://github.com/Memotech-Bill/OpenSpin
The code probably needs further testing, but it does everything that I want, and I can go back to trying to work out what is wrong with my Propeller code.
0000 03D09000 Frequency 64000000 0004 67 Clock Mode 0005 D9 Check Sum 0006 0010 Base of Program 0008 6D9C Base of Variables 000A 75D4 Base of Stack 000C 01C4 Initial Program Counter 000E 75D8 Initial Stack Pointer File "MTX_Monitor_11.spin" 0010 1580 0417 Link to Next Object 0014 01B4 0000 Link to MAIN 0018 0235 0000 Link to GETPOS <<< Many lines omitted >>> PUB Main BufIn := 0 01C4 35 ; Push_0 01C5 41 ; Pop_Varmem_Long_0 BufOut := 0 01C6 35 ; Push_0 01C7 45 ; Pop_Varmem_Long_1 inp.Start (@Buffer, @BufIn, @BufOut) 01C8 01 ; Frame_Call_Noreturn 01C9 8B 20 ; Reference_Variablemem_Byte, $0020 01CB 43 ; Reference_Varmem_Long_0 01CC 47 ; Reference_Varmem_Long_1 01CD 06 1801 061A ; Objcall, $1801, $061A Text := vdp.GetBuffer 01D0 00 ; Frame_Call_Return 01D1 06 1A02 0006 ; Objcall, $1A02, $0006 FontAddr := vga.FontLoc 01D5 00 ; Frame_Call_Return 01D6 06 1703 0148 ; Objcall, $1703, $0148 <<< Many lines omitted >>> File "MTX_Video_8.spin" 1590 2BA0 0004 Link to Next Object 1594 2B30 0008 Link to START 1598 2B84 0004 Link to STOP 159C 2B9B 0000 Link to FONTLOC DAT 000 org 15A0 000 5C7C00A5 video jmp #init0 15A4 001 A2BD47F0 vsync mov tpage1, par wz ' Test for first cog 15A8 002 A0BD47F1 mov tpage1, cnt ' Get current time 15AC 003 082946A2 if_z wrlong tpage1, pagead ' Save time for first cog to hub ram 15B0 004 A0FD4E02 mov line_cnt, #vs ' Number of lines of vertical sync 15B4 005 5CFD0E7B call #blank_vsync ' Output sync pulse 15B8 006 08BD48A2 rdlong tpage2, pagead ' Fetch time of first cog 15BC 007 84BD48A3 sub tpage2, tpage1 ' Time difference between cogs 15C0 008 A0FD4E1A vb_lines mov line_cnt, #vb - 8 ' Number of lines in vertical back porch (cog 0 starts 8 lines early) 15C4 009 5CFD0E7B call #blank_vsync ' Output back porch <<< Many lines omitted >>> Variables for TOP (MTX_Monitor_11.spin) 6D9C long BUFIN 6DA0 long BUFOUT 6DA4 long TEXT 6DA8 long TTOP 6DAC long DATPTR 6DB0 long PATPART 6DB4 long FONTADDR 6DB8 long DATCTR 6DBC byte BUFFER[2048] 75BC byte GDAT[6] Variables for TOP.VGA (MTX_Video_8.spin) 75C4 byte COG[3] Variables for TOP.INP (MTX_Input_2.spin) 75C8 byte NCOG 75CC Reserved 8 bytes. 75D4 Base of stack. 75E4 Top of stack.
Comments
I hope we can get that 'officially' soon.
Where can I sign the e-petition?
:-D
Just need to fixup the changes he made to the banner when you run it and the readme
I have compiled your source on Linux and found a couple of issues:
1. Without the new -l on the command line it gives a segmentation error (missing some null checks ?)
2. Compiling one of my projects, the listing is a bit weird, I tried to reproduce on a smaller source without success, here is an excerpt:
I tried the same command line on other projects and doesn't seems to have issues. This particular source uses conditional compiles (#ifdef, etc.), maybe an incompatibility with that feature ?
A suggestion: allow to write the listing on a file instead of stdout.
Keep up the good work!
Thank you for the pointers. I am still fairly new to the Propeller community, and dit not know what to search for.
@Roy Eltham
Flattered. My main concern at the moment would be the translation of the binary into byte-code mnemonics. In particular the interpretation of the op_Effect and op_Unsigned_Effected_Offset parameters of some byte-codes.
@macca
I will look into this.
Segfault resolved by latest commit.
With the example you show is being listed in Object Link format, and then is being listed in PASM format.
Without a copy of the source code I am unable to determine the cause. Are you able to post the source?
Looks like an issue with the conditional compilation, I modified a sample hello world in the spin standard library as follows:
And the listing shows this:
Attached is a zip file with the sources. Compile with and without -DTEST to see the difference.
Quite right. In order to generate the listing I re-load the source files, and I was not pre-processing them correctly so my text pointers were not pointing to the correct place in the source. Should be corrected by my latest commit.
An alternative would have been to keep an in-memory copy of the source code when it is first loaded by the compiler, however that could have resulted in a substantial increase in memory usage.
You suggested re-directing the listing to a file. I can see some advantages to that, however I am not sure how best to do that on the command line. Possibilities:
* Listing could always go to <source name>.lst
* -l switch could always take a file name, with "-" to select stdout.
* Could use the syntax -l=<filename>
Which would be preferred?
Very good, works perfectly now, even with the other bigger project. Thank you!
While you are at it, check also if there is a similar issue with the -u (unused method elimination), I don't have evidence of any, just to be sure.
With today's available memory I don't see it as a problem, after all OpenSpin won't run on a 64k system and the sources are few hundreths kbytes at most, on complex projects.
For me, a listing should always be written to a file, since it is intended as a way to see what the compiler actually has produced so in my opinion doesn't make sense to have it on stdout at all. Maybe try with multi-letter parameter: -l write to file <output>.lst, -lc write to console output. Also I think it would be better to use the output file name (as specified by -o or default) instead of the source file so it is possible to compile projects with conditional compilation and save the related listing.
Good call. Unused method elimination also causes problems, although for different reasons. This is going to take a bit more work.
Unused method elimination basically does 2 compiles of everything. The first one compiles as "normal" but tracks the info needed to know what's used and what's not, then the second one uses the info while compiling to skip unused stuff.
If you can have your stuff "off" during the first compile, then on for the second one, that should work out I think.
There are now three listing options:
-lc Lists to stdout
-lo Lists to <output>.lst
-lf <filename> Lists to named file.
Other minor changes:
* Variables are now listed with their relative address from the top of the current variables block as well as their absolute address. Spin byte-code references variables by their relative address.
* Minor improvements to the interpretation of the Spin byte-code
Excellent, thank you very much!
Working on it.
The only outstanding item I am aware of is possible incorrect translation of some of the more obscure byte-codes. Even then the bytes listed on the left hand side will be correct, and the translation will recover at the next source code line.
Does anyone have an example of Spin code which generates byte-codes $86, $8A or similar? If I understand correctly these could in principle be followed by an address (1 or 2 bytes), an effects byte and another address (1 or 2 bytes), giving a maximum instruction length of 6 bytes.
The attached code is just Chip's Vocal Tact Demo and driver. I'm running on macOS 10.15.4 (Catalina).
dgately
Thank you for your error report. There was a typo in the code for listing the variables for an array of objects, which I have corrected in the latest commit. Hopefully this will resolve the problem.
See the punt/spin latest version (v34r)
I think this is similar to your SpinBytecodeDoc_600_260C_007F.spin from forums.parallax.com/discussion/111684/spin-bytecode which I have been using in conjunction with https://github.com/rosco-pc/propeller-wiki/wiki/Spin-Byte-Code
I just wanted to check my understanding.
So if the "i" bit is set this is followed by a one or two byte offset. Then if "oo" = %10, this is followed by a "using" or "effects" byte:
So if this has the value %-0000s1- this is followed by another address.
Is this plausible or is this a pathological case that would never occur in practice?
What I was really looking for is some short examples of Spin code, which when compiled generated the various forms of byte-code. Is there a test suite for the openspin compiler?
This is your listing:
This is the listing produced by bstc:
As you can see, at address 0302 there are two filler bytes needed to align the dat section to a long boundary, your listing consider them as part of the following dat section and interpret them as the first instruction, which is wrong. Note also that the controller_cog and tx_count labels are missing. The bstc listing dosn't show the filler bytes but the following instruction is correct.
I'm attaching the source here, it is part of the usb-host controller code from
https://github.com/SaucySoliton/propeller-usb-host/
Best regards,
Marco
I have revised this and openspin now produces:
As an aside note, a slightly modified version of the USB code can be found here.
You should look at using the listings from homespun and bst (they each have advantages). Hopefully then you can contrive some examples to generate the required bytescodes and look at their generation. Sorry I can't be of much help.
It turns out that yes it is possible to have two addresses, one preceding and one following the "using" byte:
The line at 007F illustrates this: The first address is the location (relative to the start of the object) of the loop variable, and the second address is the offset to the start of the loop ($0083 + $FFF4 = $0077 in signed arithmetic).
In this case, because the addresses are small they have been encoded as single bytes.
@Cluso99, one tiny piece of new information, the address following a "using" code of "-0000s1-" is a signed offset.