[TI ASM] Parser and Compiler

Got questions? Got answers? Go here for both.

Moderator: MaxCoderz Staff

ssartell
Regular Member
Posts: 76
Joined: Fri 02 Dec, 2005 5:39 pm

[TI ASM] Parser and Compiler

Post by ssartell »

I figured I'd move my topic over to here since it didn't really relate to the post it was in and maybe people would see it in here. So I'm writing a compiler for C/C++ for z80 asm (trying to do so anyways). I'm still working on the parsing code into abstract syntax trees, but it's coming along. Once I get that done I'll be working on actually translating it into asm code which might prove to be the most difficult part. I'm going to make my best effort to make the compiler smart about where it stores it's data and what not, but it'd be really helpful to me if the expert asm people could fill me in on any conventions for z80 asm. Are there certain registers usually used for calling arguements? Are registers callee saved, caller saved, or split between them? I would like to try and keep everything data in registers as much as possible, but this might prove to be challenging. Are there any conventions to storing data to memory? I need to know stuff like to make things run as best as possible.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

There are no 'standard' registers used for calling arguments - you write your functions with certain input and output registers in mind - of course, this limits recursion.

Useful registers, however, are the index registers ix and iy. These index registers can be set to a particular value, then you can easily use them to read/write to memory via an offset - for example, ld a,(ix+5) or ld (iy-4),0

One 'easy' way (albeit inefficient) of calling functions would be to push all of the arguments onto the stack then call the function, and the function would then pop the arguments back off again (this makes recursion very simple).

However, as you have very limited stack-space, it might be better to store the arguments somewhere in RAM and only push a pointer to these variables to the stack before calling. You could then pop into IX and use the index registers to access the individual arguments.

Without wanting to sound entirely self-whoring, if you don't intend to write your own assembler, using Brass with nested modules and the .var/tvar directives would no doubt make allocating variables (local or otherwise) much simpler. ;) (I have had, in the background, the idea of writing a C-ish compiler for the Z80, hence these features in Brass).
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

Are there certain registers usually used for calling arguements?
I usually use a for bytes and and hl for words, if I need more I move on to b, c or de.
Are registers callee saved, caller saved, or split between them?
Depends on the situation, I guess. And on who you ask.
Are there any conventions to storing data to memory?
Yup, use the "saferams". 768 bytes at plotsscreen, 512 bytes at statvars, et cetera. But it isn't much, so you may need to use the free ram in the vat...

Edit: Ah, well, cross-post...
However, as you have very limited stack-space, it might be better to store the arguments somewhere in RAM and only push a pointer to these variables to the stack before calling. You could then pop into IX and use the index registers to access the individual arguments.
Good thinking, Ben :)
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
ssartell
Regular Member
Posts: 76
Joined: Fri 02 Dec, 2005 5:39 pm

Post by ssartell »

What do you guys think about type checking? There are a lot of restrictions in C/C++ because of type checking that someone could get around if I just neglect to check types. And it'd make my life easier. Any thoughts?
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

The way I'd do it is I'd structure things so that different types have different rules.

The base types I'd at least start with would be byte, ubyte, short and ushort. Then I'd have different rules for the operators (for example, comparing a ubyte to a ubyte would be different to comparing a byte to a byte). Making sure that the types match up is imperative.

I'd have thought that not checking types makes your life more difficult and things unpredictable. I'd also make explicit casting between two different types that don't have an operator defined mandatory.
ssartell
Regular Member
Posts: 76
Joined: Fri 02 Dec, 2005 5:39 pm

Post by ssartell »

I had always planned on having it typed, but I just don't think I want to check if you're using the right types for certain things. Like if you pass in a wrong typed arguement for some function, I don't really want to check for that. I can, but it'd take a while...
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

The point of using types is having lots of potential errors caught at compile time and also producing more efficient executables. The type system is a fundamental building block of a language, and you should put a lot of thought into designing it. You have to define ranges, operations (including error conditions like overflow) and coercion rules with care. I'd include the following primitive types: signed and unsigned integers of 8, 16, 24 and 32 bits, fixed point numbers (multiplication and division need to be optimised for them in a special way) of various precisions, boolean (so the compiler knows it could as well be just a flag), character and string (self-managing). To describe composite data I'd only use arrays and records, maybe unions too.

And I think you should forget about C. It's too 'strong' a language in my opinion, that's why there is no efficient compiler for it to date. If I were to design a language for this platform, I'd constrain it as much as possible, e. g. I would probably avoid pointers (use much more restricted references instead) and goto (not for academic reasons; goto can really mess up optimisation), let alone objects, generics and other complex structures.
ssartell
Regular Member
Posts: 76
Joined: Fri 02 Dec, 2005 5:39 pm

Post by ssartell »

well I'm still working out just parsing everything into an abstract syntax tree so I've got sometime to plan and decide things before I try and tackle that part.
User avatar
L4E_WakaMol-King
Maxcoderz Staff
Posts: 342
Joined: Tue 01 Nov, 2005 6:34 am

Post by L4E_WakaMol-King »

That's ironic... we just went over parsing trees and compilers today in one of my classes. Good luck... it will be a hell of a lot of work.
Image - Now Under Development - [Progress]
ssartell
Regular Member
Posts: 76
Joined: Fri 02 Dec, 2005 5:39 pm

Post by ssartell »

Ehh, it's not that terrible. I have it parsing just about everything except for loops, function applications, and function declarations. I'm still deciding exactly how I want to work with each one.
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

But what are you parsing? You have already decided on syntax before working out what to include in the language? At least I really don't recommend making another C compiler.
ssartell
Regular Member
Posts: 76
Joined: Fri 02 Dec, 2005 5:39 pm

Post by ssartell »

I was shooting for C/C++/Java style. I'm just working on getting the basics going right now (operations, assignments, declarations, functions, basic statements). Deciding on specific types and what not doesn't need to be done now. I'm just parsing the given code text into an abstract syntax tree so that it's easy to translate and type check. Is there any reason not use this sort of style?
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

Certainly it's partly personal preference. To me it makes more sense to do it in this order:

1. Deciding on language features
2. Working out type system (and everything related)
3. Dealing with structure (scoping, blocks, interfaces...)
4. Describing the semantics of control constructs
5. Creating syntax (reserved words, delimiters, anything) and writing some example code
6. Generating parser (there are ready-made tools for this)
7. And now I can start thinking about compilation...

The first five steps are purely paperwork. Writing example code (simple applications or games) and running it in head (elaborately, tracking all the values generated including the implicit conversions and such) is a vital step, because it helps you discover design errors before jumping in the implementation phase.
ssartell
Regular Member
Posts: 76
Joined: Fri 02 Dec, 2005 5:39 pm

Post by ssartell »

Well I've never written a full compiler and parser and I'm not even that great at z80 asm so I'm just kinda playing it by ear and see what happens. If someone else wants to take a more serious shot at this, then by all means go for it. I'm mainly playing around with this cause it sparked my curiousity and I have some down time between semesters to play around with stuff. I haven't decided anything beyond the language will have operations, assignments, typical controls structures, some basic types (I'm not even working on implementing these yet cause I'm still just parsing stuff out into a syntax tree), and functions. I haven't gotten past reading in code from a file into my syntax tree. Once I do, then I'll worry about implementation of each feature including what types I want and how they are going to work.
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

But why are you wasting time on the parser, which is practically the only component you can generate with existing tools?
Post Reply