stev47 wrote:
Hello,
I just noticed that you forked my old z80 codebase and am amazed that you are willing to work on the llvm backend.
Some quick notes:
Take a look at this project:
http://sourceforge.net/projects/llvmz80/
It seems to be active and might be a better starting point than my old codebase.
I can recommend the llvm-talk "Tutorial: Building backend in 24 hours":
http://www.llvm.org/devmtg/2009-10/
If I remember correctly there was a more recent talk on backend building (or rather a workshop) but I can't find it at the moment.
From what I understand it is advisable to work with a more recent version of llvm and staying more or less up to date with the releases.
If you stay at 3.1 and need some features from top of tree someday you may have a lot of work.
As far as git workflow is concerned:
In opposition to svn you have branches and it is recommended to work on a personal branch whenever possible. There you add features/fixes and test them. You merge them afterwards into the master branch (preferably rebasing first (if your branch isn't public) to prevent merge commits).
This way you won't have problems to pull from upstream as the pull from the master branch will always be a fast-forward one.
Anyways, keep up the work.
stev, thanks for feedback, I will try and get us up to date with the main version (I was being cautious and sticking to 3.1, since development branches are sometimes unstable), and take a closer look at the Sourceforge project you mentioned. A quick look seems as if they've made decent progress. I suspect they will have different design goals than we do, but if it appears to be functional, it may make a good place to start. The repository certainly seems active.
I've been a long time svn user, so it'll probably take a bit to adjust to the new workflow. Good work tracking us down, btw.
There is a simple 16-bit target called DCPU-16 for which a llvm backend has been developed.
You can take a look at the code here:
https://github.com/llvm-dcpu16/llvm-dcpu16/tree/dcpu16/lib/Target/DCPU16
The amazingly short cpu documentation can be found here:
http://dcpu.com/dcpu-16/
The sourceforge project did not fork from my codebase as far as I can see.
I'm still interested in this project and would like to contribute as far as time permits (currently I'm rather busy studying).
Do you have any particular platforms you'd like to support, or design requirements to meet? or just an interest in z80 in general? As you may have noticed/guessed, we have a particular interest in supporting TI hardware and emulators. One of the first things I started on in our fork was subtargets to allow us to control whether or not undocumented instructions are emitted as the z80 emulators produced by TI don't support them (their official SDK for the TI-8x line, and the TI-84+ snap-in keypad for the TI-Nspire).
Poll: accessing ports and absolute-addressed variables.
In SDCC, you can read and write to IO ports by making a variable like:
Code: // From GlassOS project's global.h
__sfr __at 0x00 Port_Link;
__sfr __at 0x01 Port_Keyboard;
__sfr __at 0x02 Port_Status;
__sfr __at 0x03 Port_Interrupt_Mask;
__sfr __at 0x04 Port_Mem_Map;
__sfr makes it use a port __at a port number.
As you can see, __at here specifies the port number, but it can also designate memory locations. See this example:Code: // From GlassOS project's global.h
__at 0xB100 unsigned char* lcd_buffer;
__at 0xBB10 volatile unsigned char var_lcd_x;
__at 0xBB11 volatile unsigned char var_lcd_y;
__at 0xBB12 volatile unsigned char var_lcd_invert;
__at 0xBB13 volatile unsigned char var_lcd_size; // Font size, 1 = big, 0 = small
In this case, I specify the address it is located at.
Is theer anyway that LLVM can do something like this? Port usage is a must, but __at 0xB100 ... could be done with a const pointer... maybe
<edit>
Elfprince: SDCC proposed that to be togglable at compile-time (--enable-undocumented-ops or something). I think we should use them, but not a priority. Maybe get [ix|iy][l|h] in while we are at it, but other crazy ops for later. You never know if the output can be optimized with undocumented ops in ways that we don't.
We can have multiple address spaces (possibly even with different pointer sizes) but I don't know too much about how LLVM treats them. Should be doable though. I was thinking it could be helpful to be able to have pointers to Flash addresses that include the page #.
It's quite easy to add all the instructions, but disallow the undocumented one by subtarget. This is how the Sparc example differentiates between the 32bit and 64bit targets.
Is that how X86 has the MMX, SSE, etc. (how you tell LLVM to use it or not, that is)?
Presumably similar. I haven't looked at the x86 Target too closely yet.
elfprince13 wrote:
Do you have any particular platforms you'd like to support, or design requirements to meet? or just an interest in z80 in general? ...
The only z80 device I own is a TI-83+ calculator, so I would like to support that one at least.
I think clang compiler support is a "must have" (after getting some llvm-ir compiled).
AHelper wrote:
Is that how X86 has the MMX, SSE, etc. (how you tell LLVM to use it or not, that is)?
Generally you specify the target through the -march and -mcpu command line options which get translated into respective intstruction capabilities.
With -mattr=... you can manually select architecture specific attributes.
For example the list of options for the x86 target:
Code: $ llvm-as < /dev/null | llc -march=x86 -mattr=help
Available CPUs for this target:
amdfam10 - Select the amdfam10 processor.
athlon - Select the athlon processor.
athlon-4 - Select the athlon-4 processor.
athlon-fx - Select the athlon-fx processor.
athlon-mp - Select the athlon-mp processor.
athlon-tbird - Select the athlon-tbird processor.
athlon-xp - Select the athlon-xp processor.
athlon64 - Select the athlon64 processor.
athlon64-sse3 - Select the athlon64-sse3 processor.
atom - Select the atom processor.
bdver1 - Select the bdver1 processor.
bdver2 - Select the bdver2 processor.
btver1 - Select the btver1 processor.
c3 - Select the c3 processor.
c3-2 - Select the c3-2 processor.
core-avx-i - Select the core-avx-i processor.
core-avx2 - Select the core-avx2 processor.
core2 - Select the core2 processor.
corei7 - Select the corei7 processor.
corei7-avx - Select the corei7-avx processor.
generic - Select the generic processor.
geode - Select the geode processor.
i386 - Select the i386 processor.
i486 - Select the i486 processor.
i586 - Select the i586 processor.
i686 - Select the i686 processor.
k6 - Select the k6 processor.
k6-2 - Select the k6-2 processor.
k6-3 - Select the k6-3 processor.
k8 - Select the k8 processor.
k8-sse3 - Select the k8-sse3 processor.
nehalem - Select the nehalem processor.
nocona - Select the nocona processor.
opteron - Select the opteron processor.
opteron-sse3 - Select the opteron-sse3 processor.
penryn - Select the penryn processor.
pentium - Select the pentium processor.
pentium-m - Select the pentium-m processor.
pentium-mmx - Select the pentium-mmx processor.
pentium2 - Select the pentium2 processor.
pentium3 - Select the pentium3 processor.
pentium3m - Select the pentium3m processor.
pentium4 - Select the pentium4 processor.
pentium4m - Select the pentium4m processor.
pentiumpro - Select the pentiumpro processor.
prescott - Select the prescott processor.
westmere - Select the westmere processor.
winchip-c6 - Select the winchip-c6 processor.
winchip2 - Select the winchip2 processor.
x86-64 - Select the x86-64 processor.
yonah - Select the yonah processor.
Available features for this target:
3dnow - Enable 3DNow! instructions.
3dnowa - Enable 3DNow! Athlon instructions.
64bit - Support 64-bit instructions.
64bit-mode - 64-bit mode (x86_64).
aes - Enable AES instructions.
atom - Intel Atom processors.
avx - Enable AVX instructions.
avx2 - Enable AVX2 instructions.
bmi - Support BMI instructions.
bmi2 - Support BMI2 instructions.
cmov - Enable conditional move instructions.
cmpxchg16b - 64-bit with cmpxchg16b.
f16c - Support 16-bit floating point conversion instructions.
fast-unaligned-mem - Fast unaligned memory access.
fma - Enable three-operand fused multiple-add.
fma4 - Enable four-operand fused multiple-add.
fsgsbase - Support FS/GS Base instructions.
idiv-to-divb - Use small divide for positive values less than 256.
lea-sp - Use LEA for adjusting the stack pointer.
lzcnt - Support LZCNT instruction.
mmx - Enable MMX instructions.
movbe - Support MOVBE instruction.
pclmul - Enable packed carry-less multiplication instructions.
popcnt - Support POPCNT instruction.
rdrand - Support RDRAND instruction.
slow-bt-mem - Bit testing of memory is slow.
sse - Enable SSE instructions.
sse2 - Enable SSE2 instructions.
sse3 - Enable SSE3 instructions.
sse41 - Enable SSE 4.1 instructions.
sse42 - Enable SSE 4.2 instructions.
sse4a - Support SSE 4a instructions.
ssse3 - Enable SSSE3 instructions.
vector-unaligned-mem - Allow unaligned memory operands on vector/SIMD instructions.
xop - Enable XOP instructions.
Use +feature to enable a feature, or -feature to disable it.
For example, llc -mcpu=mycpu -mattr=+feature1,-feature2
AHelper wrote:
Poll: accessing ports and absolute-addressed variables.
In SDCC, you can read and write to IO ports by making a variable like:
Code: // From GlassOS project's global.h
__sfr __at 0x00 Port_Link;
__sfr __at 0x01 Port_Keyboard;
__sfr __at 0x02 Port_Status;
__sfr __at 0x03 Port_Interrupt_Mask;
__sfr __at 0x04 Port_Mem_Map;
__sfr makes it use a port __at a port number. I've seen this pattern in other compilers targeting embedded systems, but I don't think it's desirable to go adding extensions like that in this case.
A good way to approach this sort of problem, I think, is to handle it all in the linker. For example, avr-libc provides some section annotation shortcuts to put data in program memory:Code: // <avr/pgmspace.h>
#define PROGMEM __attribute__(__progmem__)
// Puts the string in program memory
unsigned char *foo PROGMEM = "Hello, world!";
System-reserved locations are usually just done with const pointers, as you noted. Common pattern for memory-mapped registers:Code: volatile uint16_t *const MMR_FOO_H = 0xC002;
You might be able to combine these patterns to have an I/O space section, but I'm not entirely sure. I suspect you can define some sort of attribute that your backend recognizes as requiring in/out instructions rather than direct memory accesses.
I think page-flipping is best handled at the program-level, rather than by the compiler. This target is deeply-embedded enough that it's useful to have direct control over those mechanisms. It's easy to provide some convenience macros to simplify the process, but I think that should be exposed to the programmer.
Quote:
I've seen this pattern in other compilers targeting embedded systems, but I don't think it's desirable to go adding extensions like that in this case
Well, considering the CPU, having some method to writing to the ports are needed. I was simply stating how SDCC does it. I would love it if it can be done some way.
The problem with the SDCC method is, what if you want to use out (c),a? Would it be possible to use out (xx),a and out (c),a at all? Function/macro like? New datatype?
stev47 wrote:
elfprince13 wrote:
Do you have any particular platforms you'd like to support, or design requirements to meet? or just an interest in z80 in general? ...
The only z80 device I own is a TI-83+ calculator, so I would like to support that one at least.
I think clang compiler support is a "must have" (after getting some llvm-ir compiled).
You're into calculator programming enough to start on a z80 target for LLVM, but we've never seen you here before? Welcome aboard!
Ultimately, I would like to see all sorts of llvm-friendly compilers be supported (I suspect Tari would appreciate support for ghc).
AHelper wrote:
Well, considering the CPU, having some method to writing to the ports are needed. I was simply stating how SDCC does it. I would love it if it can be done some way.
I would suggest we support inline assembly, but also provide a standard library to handle I/O, and hide it there so that most programmers don't have to deal with it directly.
elfprince13 wrote:
You're into calculator programming enough to start on a z80 target for LLVM, but we've never seen you here before? Welcome aboard!
Welcome indeed; great to have you with us. While we're on the topic, would you care to Introduce Yourself?
Quote:
I would suggest we support inline assembly, but also provide a standard library to handle I/O, and hide it there so that most programmers don't have to deal with it directly.
What do you have in mind? I would strongly go against anything that doesn't inline itself. Port_write(byte portNum, byte data); that generates out (xx),a inlined in the caller, not as a function call. For that, I am all for.
For putting variables at specific locations, can I make the linker handle groups? Like, I have an ISR variable area, process register backup area, etc. that have a starting address, and I also have a group that must be stored to in descending order. Would the linker handle these cases, or would absolute references be the only way to handle it? If the linker can work, how do I specify where things go?
AHelper wrote:
What do you have in mind? I would strongly go against anything that doesn't inline itself. Port_write(byte portNum, byte data); that generates out (xx),a inlined in the caller, not as a function call. For that, I am all for.
Quote:
For putting variables at specific locations, can I make the linker handle groups? Like, I have an ISR variable area, process register backup area, etc. that have a starting address, and I also have a group that must be stored to in descending order. Would the linker handle these cases, or would absolute references be the only way to handle it? If the linker can work, how do I specify where things go?
Ideally, during compilation we should be generating relocatable object files, and allow the linker to worry about where things should be put in memory.
Well, I know that it can arrange stuff in the linker. Just wondering if you can specify which location. Not needed to know now
Still learning the syntax of TableGen.
Incidentally, I don't see why this
Code: __at 0xBB10 volatile unsigned char var_lcd_x;
couldn't be done like this:
Code: volatile unsigned char *var_lcd_x = (unsigned char *)0xBB10;
elfprince13 wrote:
Ultimately, I would like to see all sorts of llvm-friendly compilers be supported (I suspect Tari would appreciate support for ghc).
Hah, that would be awesome, but I fear unfeasible (or very limited). The lazy nature of Haskell makes it fairly memory-hungry and I believe it requires a runtime library for memory management.
elfprince13 wrote:
AHelper wrote:
Well, considering the CPU, having some method to writing to the ports are needed. I was simply stating how SDCC does it. I would love it if it can be done some way.
I would suggest we support inline assembly, but also provide a standard library to handle I/O, and hide it there so that most programmers don't have to deal with it directly. Agreed. Provide libraries for common tasks, with the possibility for users to directly write hardware access code if necessary.
Leave inlining up to the optimizer. As long as you don't have optimizations turned off, it's very likely that it'll go ahead and inline such short functions.
AHelper wrote:
For putting variables at specific locations, can I make the linker handle groups? Like, I have an ISR variable area, process register backup area, etc. that have a starting address, and I also have a group that must be stored to in descending order. Would the linker handle these cases, or would absolute references be the only way to handle it? If the linker can work, how do I specify where things go?
Just define a section in the object file for things as needed. It sounds to me like most of the use cases you mention there are things that the runtime environment provides though, so you should just query whatever sets them up to get pointers rather than try to resolve them at compile-time.
elfprince13 wrote:
Incidentally, I don't see why this
Code: __at 0xBB10 volatile unsigned char var_lcd_x;
couldn't be done like this:
Code: volatile unsigned char *var_lcd_x = (unsigned char *)0xBB10;
For TIOS, you don't typically just start spurting out memory addresses for your variables. You would do something like SAFERAM+2 or something. That is what I am looking for.
The thing I was trying to look for was something like: char foo[] __attribute__(section('.data.catfish')) = "CATFISH";
For common saferam, you shouldn't even need to do anything fancy. Just define your .data section to be where you have some safe memory. GNU ld syntax would be like so:
Code: MEMORY
{
/* appBackUpScreen */
saferam (rwx) : o = 0x9872, l = 768
}
SECTIONS
{
.data {
*(.data)
*(.data.*)
} > saferam
}
The compiler emits static allocations in the .data section on its own, so it Just Works.
Spanning a single section over multiple memory regions may be tricky though, since I don't think '> saferam > saferam2' or so is legal. That might require linker hacks to do.
Major progress: I started with a fresh llvm trunk snapshot and readded the Z80 target. I applied a patch to the cmake system to get everything to compile. I fixed all of the .td errors and got all .inc's generating. Now, I get a nice "No instructions defined!".
What should I do with this?
<edit>
There are about 13,000 changed files from what we currently have in github.
<edit>
Trying to understand DAG's and, specifically, SDNode and friends. Any pointers?
<edit>
Dumping guide here:
http://llvm.org/devmtg/2009-10/Korobeynikov_BackendTutorial.pdf
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.
»
Go to Registration page
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 vote in polls in this forum