6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue May 14, 2024 9:12 pm

All times are UTC




Post new topic Reply to topic  [ 82 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next
Author Message
PostPosted: Sun May 01, 2022 11:08 am 
Offline
User avatar

Joined: Sat Jul 24, 2021 1:37 pm
Posts: 282
I've been reading the docs for the 65816 and this might be a dumb question but I haven't seen it mentioned there: Is Calypsi running in 16bit mode or 8bit mode? Does it switch automatically as needed? Or is this something you have to define yourself, if so how?

_________________
BB816 Computer YouTube series


Top
 Profile  
Reply with quote  
PostPosted: Sun May 01, 2022 7:18 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8183
Location: Midwestern USA
akohlbecker wrote:
Is Calypsi running in 16bit mode or 8bit mode? Does it switch automatically as needed? Or is this something you have to define yourself, if so how?

I'll interject here.

The 65C816 has no “16-bit mode” or “8-bit mode.” The only modes are emulation and native. In native mode, registers may be set to 8- or 16-bits width.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sun May 01, 2022 7:45 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8433
Location: Southern California
BigDumbDinosaur wrote:
akohlbecker wrote:
Is Calypsi running in 16bit mode or 8bit mode? Does it switch automatically as needed? Or is this something you have to define yourself, if so how?

I'll interject here.

The 65C816 has no “16-bit mode” or “8-bit mode.” The only modes are emulation and native. In native mode, registers may be set to 8- or 16-bits width.

...and you can set the accumulator to 8 or 16, and the index registers to 8 or 16, independently, for example have 16-bit accum and 8-bit X & Y, or vice-versa, or both 8- or both 16-bit. When you first go into native mode, these start out as 8-bit, and you can switch as often as you like, all in native mode.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sun May 01, 2022 8:11 pm 
Offline
User avatar

Joined: Sat Jul 24, 2021 1:37 pm
Posts: 282
Thanks. I'll rephrase my question in case there is doubt about what I meant: Is Calypsi generally executing code by default using 16 bit memory accesses or 8 bit accesses, is it switching the indexes or accumulator sizes itself automatically (depending on type size for example?), or do you have to manage this yourself. If so, how?

_________________
BB816 Computer YouTube series


Top
 Profile  
Reply with quote  
PostPosted: Tue May 03, 2022 9:41 pm 
Offline

Joined: Sun Oct 07, 2018 6:04 pm
Posts: 30
akohlbecker wrote:
Thanks. I'll rephrase my question in case there is doubt about what I meant: Is Calypsi generally executing code by default using 16 bit memory accesses or 8 bit accesses, is it switching the indexes or accumulator sizes itself automatically (depending on type size for example?), or do you have to manage this yourself. If so, how?


The compiler run-time always run with 16-bit index register enabled. It will normally run with 16 bit data enabled, but will switch to 8 bit when required and then go back to 16 bit data. This happens automatically and there is nothing you need to do to make it happen.

The code generator tries to stay in 16 bit mode as much as possible. When reading 8 bit (or 24 bit) data, it will access it as 16 bits if it can to reduce data mode changes. 24 bit pointers are treated as 32 bit objects for this reason. Volatile accesses are done in their specified size and there is a __far24 attribute for the situations where you must have a 24 bit type.

If you call your own assembly routines, you can rely on that the index and data size are 16 bit when called. You can change it internally but you need to give control back with 16 bit index and data size enabled.


Top
 Profile  
Reply with quote  
PostPosted: Tue May 03, 2022 10:23 pm 
Offline
User avatar

Joined: Sat Jul 24, 2021 1:37 pm
Posts: 282
Thank you for your answer, much appreciated.

Is there an optimization where it sees multiple 8-bit accesses in succession and decides to switch M to 8-bit? Considering 16-bit accesses have a one-cycle penalty. You said "when required" but it is unclear to me what those cases are?
This comes to mind because I'm currently working (in assembly, haven't switched to C yet) on hardware drivers where most of the accesses and data manipulated are 8-bit (things like reading keyboard keys and writing to an LCD), and so they would benefit from a mode change at the beginning of the subroutine.

_________________
BB816 Computer YouTube series


Top
 Profile  
Reply with quote  
PostPosted: Tue May 03, 2022 10:42 pm 
Offline

Joined: Sun Oct 07, 2018 6:04 pm
Posts: 30
akohlbecker wrote:
Thank you for your answer, much appreciated.

Is there an optimization where it sees multiple 8-bit accesses in succession and decides to switch M to 8-bit? Considering 16-bit accesses have a one-cycle penalty. You said "when required" but it is unclear to me what those cases are?
This comes to mind because I'm currently working (in assembly, haven't switched to C yet) on hardware drivers where most of the accesses and data manipulated are 8-bit (things like reading keyboard keys and writing to an LCD), and so they would benefit from a mode change at the beginning of the subroutine.


The compiler will try to keep the data in 16 bits and only switch to 8 when it really must (for correct behavior). It does not care that there is a cycle penalty, the idea is that mode shifts are costly. If the generated code needs to switch back and forth, there is an optimizer step that tries to eliminate redundant switching behavior, but it is more of when it happen to find it rather than that it made a plan ahead to eliminate it.

If you are concerned about 8 bit access and performance, I would suggest grouping such accesses next to each other. Then try it out and study what the compiler makes out of it. You can always contact me if there is specific code generation you want to discuss, but preferably do that on Github as I am not here on a regular basis. If the access code is very critical, you may consider writing that routine in assembly.


Top
 Profile  
Reply with quote  
PostPosted: Wed May 04, 2022 9:41 am 
Offline
User avatar

Joined: Sat Jul 24, 2021 1:37 pm
Posts: 282
Thanks again!

Maybe I missed it in the docs, but if not, a paragraph describing this behaviour might be a worthwhile addition.

_________________
BB816 Computer YouTube series


Top
 Profile  
Reply with quote  
PostPosted: Wed May 04, 2022 8:03 pm 
Offline

Joined: Sun Oct 07, 2018 6:04 pm
Posts: 30
akohlbecker wrote:
Thanks again!

Maybe I missed it in the docs, but if not, a paragraph describing this behaviour might be a worthwhile addition.

That is a good point. I added that to the section about the assembly language interface for the next release.


Top
 Profile  
Reply with quote  
PostPosted: Fri May 06, 2022 7:16 pm 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 746
Location: Germany
i'm trying out this compiler again, after finding out that WDC's Compiler doesn't support binary notation... which seemed insane.
but after a quick round of google, the C standard just doesn't have binary notation because aparently "hex is good enough", and it just so happend that GCC/LLVM and cc65 just add binary prefixes for convenience so i had no idea it wasn't an "official" feature.

anyways i've been trying for some time to get something working, but i'm getting kinda hung up on the whole segements thing.
for example: you can have "code" and "data" in the same memory, you can have "data" and "bss" in the same memory, so why can you not have "code" and "bss" in the same memory too? am i missing some setting that allows this?
other compilers like WDC's and cc65 don't care what memory you place segments in, they just stack them one after another.

speaking of "one after another", what determines the order of segments in the output file? i need a custom header at the start of the output binary that has some information about the program (ie total size of the file, entry point for program execution, and where to place the file in memory).
with cc65 i just defined a custom segment that gets placed before any of the other segments to make sure it's the first in the output binary.
with WDC's Compiler i just placed it at the start of the crt0.s file and made sure that file got linked first so it's always at the start of the output binary.
so, how can i do that with this compiler? can i just make a custom segment? do i have to place that in the startup code? (where is the startup assembly file anyways? i was not able to find one) does the linker even generate the symbols required for this kind of thing?

and lastly, on a completely different note: is the DP just used like the ZP on the 65C02? or can it be moved during runtime?
i really liked how the WDC Compiler uses the DP, after a function has been called the stack is adjusted by some amount of bytes for temporary variables (if any), and then the DP is placed ontop of the stack. so you got really fast access to the input arguments and temporary variables, and the whole thing is nest-able so you can't accidentally clobber up the DP from some parent function. so i was hoping to be able to do the same here when writting assembly routines (or just have the compiler do that automatically).
i assume it should be fine as long as i restore the DP back to where it was before the function was called.


i'm sorry if any of these are answered inside the user guide, i have been scrolling back and forth in that thing trying to find what i need and just thought directly asking would probably be better.


Top
 Profile  
Reply with quote  
PostPosted: Wed May 11, 2022 5:23 am 
Offline

Joined: Wed Nov 24, 2021 5:46 am
Posts: 1
Håkan thanks for the Calypsi toolchain. Do you have any plans to make it available on Ubuntu Linux ARM64?


Top
 Profile  
Reply with quote  
PostPosted: Thu May 12, 2022 8:36 pm 
Offline

Joined: Sun Oct 07, 2018 6:04 pm
Posts: 30
Proxy wrote:
anyways i've been trying for some time to get something working, but i'm getting kinda hung up on the whole segements thing.
for example: you can have "code" and "data" in the same memory, you can have "data" and "bss" in the same memory, so why can you not have "code" and "bss" in the same memory too? am i missing some setting that allows this?
other compilers like WDC's and cc65 don't care what memory you place segments in, they just stack them one after another.


If you have a bare metal system with ROM and RAM then you have to separate code from modifiable data. If you load a program into a RAM based system by some kernel or operating system based environment you can place things more or less how you see fit.

Calyspi is based on ROM/RAM separation, but can do the other kind too (--hosted given to the linker). The main difference between the two is that a hosted system loads initialized data into place, while on an embedded/ROM based system such data initializers are placed in ROM and copied to RAM during C startup, which is done automatically.

To have a lot of flexibility Calypsi uses many sections with different properties. They cannot just be stack after each others with no regard of memory type for reasons outlined above. There are also sections based on different address spaces, e.g. bank 00 memory, far semantics, as well as some others.

With the current release you can do more placement without specifying where sections are placed as the linker is fairly capable of figuring it out and generate a suitable placement for you. You still need to tell what memory ranges you have and the kind of memory it is (this is the type attribute, which can be ANY, so everything goes, if that is what you want). See section 6.1.2 Placing sectons in memory.

If you want your own sections you can just create them using a #pragma or with the .section directive in the assembler. They will end up with the linker who will tell you that need to mention them in the placement, by a diagnostic message.

DP is fixed in the run-time. It will get set at startup and does not move. This allows for having a couple of pseudo registers and it can also act as a short address area (tiny) for frequently addressed static data.

You can move it as you see fit in your own assembly routines, but you need to restore it before you give control back.

The reasons I decided to make it fixed is that the 65816 already provide fast access to the stack. It also avoids code to adjust it back and forth while still having a couple of scratch locations in the DP area. Another reason is to avoid complexity that could arise in very deranged cases if you have a large stack frame (beyond 256 bytes) and need to use addressing modes only on DP and they happen to be out of range. I think the WDC compiler limits the stack frame to 256 bytes, so it cannot run into this problem.
It is a tradeoff. As mentioned, you get fast access static (tiny) data area which is not provided by WDC.


Top
 Profile  
Reply with quote  
PostPosted: Thu May 12, 2022 8:44 pm 
Offline

Joined: Sun Oct 07, 2018 6:04 pm
Posts: 30
zuliani wrote:
Håkan thanks for the Calypsi toolchain. Do you have any plans to make it available on Ubuntu Linux ARM64?


Having the Calypsi tools on ARM64 is something I want, but it will not happen in the very near future. The code base uses a GHC (Haskell) compiler that is four years old. GHC has only recently got what looks like good ARM64 support.

Upgrading also affects some libraries and sadly one library has rather dramatic API changes, so it sadly is not just a simple recompile. I also need a suitable build machine and I think the newer Mac with a Linux Docker would be useful for this. I still need to get such machine and then find time to look into this.


Top
 Profile  
Reply with quote  
PostPosted: Fri May 13, 2022 11:25 am 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 746
Location: Germany
hth313 wrote:
If you have a bare metal system with ROM and RAM then you have to separate code from modifiable data. If you load a program into a RAM based system by some kernel or operating system based environment you can place things more or less how you see fit.
Calyspi is based on ROM/RAM separation, but can do the other kind too (--hosted given to the linker). The main difference between the two is that a hosted system loads initialized data into place, while on an embedded/ROM based system such data initializers are placed in ROM and copied to RAM during C startup, which is done automatically.

To have a lot of flexibility Calypsi uses many sections with different properties. They cannot just be stack after each others with no regard of memory type for reasons outlined above. There are also sections based on different address spaces, e.g. bank 00 memory, far semantics, as well as some others.

is the need to specify if it's in ROM or RAM because the startup code is not available to the user? otherwise you could just comment out the data copying code and re-assemble it before compiling and it would be functionally identical.
you would just need to trust that the user knows the hardware it's compiling for.
but thanks for the commandline parameter, that seems to have worked. it stopped complaining about the sections.

hth313 wrote:
With the current release you can do more placement without specifying where sections are placed as the linker is fairly capable of figuring it out and generate a suitable placement for you. You still need to tell what memory ranges you have and the kind of memory it is (this is the type attribute, which can be ANY, so everything goes, if that is what you want). See section 6.1.2 Placing sectons in memory.


hth313 wrote:
If you want your own sections you can just create them using a #pragma or with the .section directive in the assembler. They will end up with the linker who will tell you that need to mention them in the placement, by a diagnostic message.

oh i see, so i'll just do the cc65 way and have a seperate assembly/object file that contains nothing but the header for the output file.
but what about the data i mentioned that is needed for the header? what symbols do i need to import to know the size of the file, or where to jump to once everything is loaded into RAM?

hth313 wrote:
DP is fixed in the run-time. It will get set at startup and does not move. This allows for having a couple of pseudo registers and it can also act as a short address area (tiny) for frequently addressed static data.

You can move it as you see fit in your own assembly routines, but you need to restore it before you give control back.

The reasons I decided to make it fixed is that the 65816 already provide fast access to the stack. It also avoids code to adjust it back and forth while still having a couple of scratch locations in the DP area. Another reason is to avoid complexity that could arise in very deranged cases if you have a large stack frame (beyond 256 bytes) and need to use addressing modes only on DP and they happen to be out of range. I think the WDC compiler limits the stack frame to 256 bytes, so it cannot run into this problem.
It is a tradeoff. As mentioned, you get fast access static (tiny) data area which is not provided by WDC.

why would the DP not work with stack frames larger than 256 bytes? The DP doesn't wrap after 256 addresses so by placing it on the top of the stack and using the 16-bit index registers you can easily address beyond the top 256 bytes into the entire stack, and the rest of Bank 0.
you can basically see the 16-bit index registers as the base address, and the 1 byte operand as the offset to that address.
it's functionally similar to the stack addressing mode, but without the 256 byte limit as the stack addressing mode only uses a single byte as offset instead of an index register.



on a different note i still can't get anything to compile even with the --hosted commandline parameter, here the error:
Code:
symbol '__program_start' referenced from section 'reset' at offset 000000 in cstartup.o: value 147945 is out of range, allowed range is -32768 to 65535

and the scm file:
Code:
(define memories'(
   (memory DirectPage   (address (#x000100 . #x0001FF))
      (section (registers ztiny)))
   (memory LoRAM    (address (#x000200 . #x00EFFF))
      (section stack heap))
   (memory IO       (address (#x00F000 . #x00F0FF)))
   (memory VRAM     (address (#x010000 . #x01FFFF)))
   (memory HiRAM    (address (#x020000 . #x08FFFF))
      (section reset data_init_table farcode code farswitch far huge cfar chuge zfar zhuge cstack))
   (block cstack    (size #x004000))
   (block stack     (size #x004000))
   (block heap      (size #x004000))
   (base-address _DirectPageStart DirectPage 0)
   (base-address _NearBaseAddress LoRAM 0)
))

the commands were just:
Code:
CC65816 --64bit-doubles --code-model large --data-model large -I Include -O2 -l -o Temp\test.o test.c
LN65816 --hosted Config\SBC_816.scm clib-lc-ld-double64.a Temp\test.o

(no header yet i want some thing working first)


Top
 Profile  
Reply with quote  
PostPosted: Sat May 14, 2022 2:07 am 
Offline

Joined: Sun Oct 07, 2018 6:04 pm
Posts: 30
The startup code is provided with the product, both in precompiled form in the library and as source code. This code is short and cruical to get the system initialized properly before you enter the main() function. It is not only doing data copying, it is also clearing variables that are 0 initialized. There may also be multiple areas that needs to be initialized.

What output format do you use? Many formats (e.g. ELF, intel-hex, S-records) contain a concept of an entry point that is supported. If you are doing Commodore PRG then https://github.com/hth313/Calypsi-6502-Commodore may offer some inspiration, though it is for 6502.

The linker error is because __program_start which is the first executable address must reside in bank 00 as the reset vector is 16 bits, but it seems you have placed it in bank 02. This should be section 'code'.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 82 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: