6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Oct 05, 2024 10:03 pm

All times are UTC




Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Thu Mar 08, 2018 6:34 pm 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
Edit: This is in reference to C02 - An 8-bit optimized C syntax compiler for the 6502

Since the status flags, Carry in particular, are often used for parameter passing. I want to devise a univeral syntax for setting and checking the status flags.

Currently, the only status flag support is in logical evaluations, and these are limited to implicitly checking the Z flag, or explicitly checking the N flag.

Examples:
Code:
  if (var)   {//do_something } //Implicit Z clear (Non-Zero)
  if (!var)  {//do_something } //Implicit Z set (Zero)
  if (var:+) {//do_something } //Explicit N clear (Positive)
  if (var:-) {//do_something } //Explicit N set (Negative)


Last edited by CurtisP on Fri Mar 09, 2018 1:23 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 08, 2018 6:58 pm 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
I was considering using the same syntax the other flags, but I can't think of any intuitive symbols for C, NC, V, NV, etc.. and I prefer to only use one character after the colon.

One option is to allow explicit checking of the zero flag:
Code:
  if (var:0)  {//do_something } //Explicit Z set (Zero)
  if (!var:0) {//do_something } //Explicit Z clear (Non-Zero)
but that's the only intuitive symbolic character I can think of.

Another option is to use single letters for set and the not operator for clear:
Code:
  if (var:C)  {//do_something } //C set (Carry)
  if (!var:C) {//do_something } //C clear (No Carry)
  if (var:V)  {//do_something } //V set (Overflow)
  if (!var:V) {//do_something } //V clear (No Overflow)
  if (var:Z)  {//do_something } //Z set (Zero)
  if (!var:Z) {//do_something } //Z clear (Non-Zero)
  etc...
This seems the most intuitive to me.

I could also use an explicit set/clear notation:
Code:
  if (var:C)  {//do_something }  //C set (Carry)
  if (var:NC) {//do_something }  //C clear (No Carry)
  if (var:V)  {//do_something }  //V set (Overflow)
  if (var:NV) {//do_something }  //V clear (No Overflow)
  if (var:Z)  {//do_something }  //Z set (Zero)
  if (var:NZ) {//do_something }  //Z clear (Non-Zero)
but I don't like the way this looks.

Finally, I was thinking of a single letter notation:
Code:
  if (var:K) {//do_something } //breaK set
  if (var:L) {//do_something } //break cLear
  if (var:S) {//do_something } //carry Set
  if (var:C) {//do_something } //carry Clear
  if (var:D) {//do_something } //Decimal set
  if (var:B) {//do_something } //decimal clear (Binary)
  if (var:I) {//do_something } //Interrupt set
  if (var:U) {//do_something } //Interrupt clear (Unset)
  if (var:M) {//do_something } //negative set (Minus)
  if (var:P) {//do_something } //negative clear (Plus)
  if (var:V) {//do_something } //oVerflow set
  if (var:W) {//do_something } //overfloW clear
  if (var:Z) {//do_something } //Zero Set
  if (var:N) {//do_something } //zero clear (Not zero)
but this is rather untuitive.


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 08, 2018 7:22 pm 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
I also need a way of setting the flags to function calls (and possibly in expressions).

C02 allows direct references to the A, X, and Y registers by name, where appropriate. I could do something similar with the flags, although this would reserve B, C, D, I, N, V, and Z from being used as variable names.
Code:
C=1; //Compiles to SEC
C=0; //Compiles to CLC
etc...
This could be done before the function call:
Code:
C=1; plot(row,col); //Set Carry before call
C=0; plot(row,col); //Clear Carry before call
or as addition parameters
Code:
plot(row,col, C=1);  //Set Carry before call
plot(row,col, C=0);  //Clear Carry before call
but this syntax would not work in expressions.

I could also use the current (or a proposed) logical evaluation syntax:
Code:
plot(row,col, :C);  //Set Carry before call
plot(row,col, :!C);  //Clear Carry before call
plot(row,col, :NC); //Clear Carry before call
plot(row,col, :-);  //Set Negative before call
plot(row,col, :+);  //Clear Negative before call
but I would want any notation to not look too strange embedded in an expression.


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 08, 2018 7:58 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 674
I've certainly thought about some of these issues in my own language design musings. Here's my opinion:

For function calls, I would make the Carry flag look like a normal parameter. So the function definition would be foo(int row, int col, carry someFlag), and the caller would do foo(10,20,1) or foo(10,20,true). Because it's C-like, the compiler should know ahead of time what the call signature is and set Carry before calling the function as a 2-parameter function instead of 3. You should add carry to the multi-register return features as well.

When using the Carry as an input or output of an addition or shift operation, I would annotate the operation, not annotate a value. So something like "a +:cin b" or "a +:cinout b" or something. It's hard to come up with a compact syntax that's readable, but at least that should be the place for it. Same thing for V as an output.

When it comes to N and Z, it's slightly different. The flag state is tied to a value rather than an operation, but it's the alu/load operations that actually do the setting of the flags on the CPU. Since you might want to capture N/Z from some inner intermediate expression whose value you're not saving, that would point to it being tied to an operation.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 08, 2018 8:05 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10949
Location: England
> Another option is to use single letters for set and the not operator for clear
That choice has my vote!


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 08, 2018 9:14 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
Would I be safe to assume this is in reference to your "C02 - An 8-bit optimized C syntax compiler for the 6502"?

If, OTOH, its for assembly, I use program flow-control structure macros and just make their names say what they do, for example:
Code:
        IF_ZERO
            FOR_X  $50, DOWN_TO, 0
                <do_stuff>
                <do_stuff>
            NEXT_X
            <do_more_stuff>
            <whatever>
        ELSE
            <do_this_>
            <other_stuff>
        END_IF

IF_ZERO assembles BNE down to the END_IF. (END_IF doesn't add anything, only fix the branch distance up at the BNE, once the address is known.) The FOR_X line assembles LDX #$50, and keeps the other information so NEXT_X knows to assemble DEX, and a BNE up to the first line after the FOR_X. (It's a little different from BASIC in that it does not run the loop for X=0, as it more closely goes with what we do in assembly; so "$50, DOWN_TO, 0" loops $50 times, not $51.) The structures can be nested, even if they're the same kind, like one IF inside another IF inside another IF.

These can be given as many names as you want, like IF_ZERO and IF_EQ are the same thing but in some cases one is more descriptive of the purpose, and other times it will be the other one. Similarly IF_NOT_ZERO and IF_NEQ. Similarly, WHILE_C_SET and WHILE_GE (greater than or equal). There are lots more of these at the link. I think it's much more readable than "if (!var:C)", just as END_IF is much more clear than } which could wrap up the wrong thing if one gets a bit careless, possibly making it a little harder for the assembler or compiler to catch structure errors.

_________________
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: Fri Mar 09, 2018 1:20 am 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
GARTHWILSON wrote:
Would I be safe to assume this is in reference to your "C02 - An 8-bit optimized C syntax compiler for the 6502"?

Yes, sorry for not being more specfic.

GARTHWILSON wrote:
These can be given as many names as you want, like IF_ZERO and IF_EQ are the same thing but in some cases one is more descriptive of the purpose, and other times it will be the other one. Similarly IF_NOT_ZERO and IF_NEQ. Similarly, WHILE_C_SET and WHILE_GE (greater than or equal). There are lots more of these at the link. I think it's much more readable than if "(!var:C)", just as END_IF is much more clear than } which could wrap up the wrong thing if one gets a bit careless, possibly making it a little harder for the assembler or compiler to catch structure errors.

Since C02 is based on C syntax, I'm pretty much stuck with the curly braces. But if I was doing a Basic like or Macro type scripting language I would definitely use something like the IF_FLAG and END_IF syntax.

Readability is important to me, though, which is why I want the syntax to be as intuitive as possible.


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 09, 2018 1:37 am 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
If I use the flag as a variable syntax, I could structure the conditionals as follows
Code:
if (func():c=0) {do something} //If Carry Clear
if (var:z=1) {do something} //If Zero set


I could even evaluate the previous operation using
Code:
if (:c=0) {do something} //If Carry Clear
if (:z=1) {do something} //If Zero set


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 09, 2018 1:48 am 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
White Flame wrote:
For function calls, I would make the Carry flag look like a normal parameter. So the function definition would be foo(int row, int col, carry someFlag), and the caller would do foo(10,20,1) or foo(10,20,true). Because it's C-like, the compiler should know ahead of time what the call signature is and set Carry before calling the function as a 2-parameter function instead of 3. You should add carry to the multi-register return features as well.

Right now, there are no function signatures. I've considered using them, but that would limit flexibility and increase the complexity of the compiler. However, function passing is positional, in the form of A, Y, X, with the ability to skip parameters using a null placeholder. I could hard code the flags as additional positions. From what I've seen, Carry is pretty much the only one ever used.

Thanks for the input.


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 09, 2018 1:51 am 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
BigEd wrote:
> Another option is to use single letters for set and the not operator for clear
That choice has my vote!

That is reasonably intuitive and quite compact.


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 09, 2018 1:54 am 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
White Flame wrote:
When using the Carry as an input or output of an addition or shift operation, I would annotate the operation, not annotate a value. So something like "a +:cin b" or "a +:cinout b" or something. It's hard to come up with a compact syntax that's readable, but at least that should be the place for it. Same thing for V as an output.

I think I'll use this with the single letter plus ! for not syntax. I'll write it up later and see how it looks.


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 09, 2018 10:45 pm 
Offline
User avatar

Joined: Sun Dec 29, 2002 8:56 pm
Posts: 452
Location: Canada
How about using the ';' rather than the ':' ? To pass more information to the statement being compiled. The 'C' for loop uses this syntax already and it'd be consistent.
So how about
if (var; C)
rather than
if (var: C)

_________________
http://www.finitron.ca


Top
 Profile  
Reply with quote  
PostPosted: Sat Mar 10, 2018 4:14 am 
Offline

Joined: Thu Feb 10, 2011 3:14 am
Posts: 79
Rob Finch wrote:
How about using the ';' rather than the ':' ? To pass more information to the statement being compiled. The 'C' for loop uses this syntax already and it'd be consistent.
So how about
if (var; C)
rather than
if (var: C)


This would work if I implemented flags as variables, but I decided not to go in that direction.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 33 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: