<sub>(This question is mostly for people who have read the tutorial by Jack Crenshaw, but since it's a well known tutorial I think it's an appropriate question).</sub>
I'm currently reading the great series "Let's Build A Compiler', by Jack Crenshaw.
I'm learning a lot and enjoying it very much. However I ran into something in the tutorial that doesn't make sense to me.
When learning how to evaluate a boolean expression, the following 'formula' for how a boolean epxression is composed is given:
<b-expression> ::= <b-term> [<orop> <b-term>]* <b-term> ::= <not-factor> [AND <not-factor>]* <not-factor> ::= [NOT] <b-factor> <b-factor> ::= <b-literal> | <b-variable> | <relation> <relation> ::= | <expression> [<relop> <expression] <expression> ::= <term> [<addop> <term>]* <term> ::= <signed factor> [<mulop> factor]* <signed factor>::= [<addop>] <factor> <factor> ::= <integer> | <variable> | (<b-expression>)
To implement this, while parsing a boolean expression, the
boolExpression function calls the
boolTerm function, which calls the
notFactor function, etc... Each function saves it's value (
0) onto a register or stack, eventually coming back to
By the time we're back at
boolExpression, the register
D0 holds the final value of the expression:
As far as I understand, <em>after</em> getting the result of the expression (which is stored in the register
D0), the flags need to be set accordingly (i.e.
TST D0 - it sets the flags of the CPU to signify information about the value in
This is so control structures such as
if can check these flags to decide what to do - obviously after the boolean expression was evaluated.
However, for some reason the tutorial puts the
TST D0 part, at the end of the
relation function, instead of at the end of the
boolExpression function - which is where I'd expect it to be.
I just can't figure out why.
boolExpression than shows several times in the book, never with
TST D0 in the end, so I know it wasn't a typo or confusion.
I would think
TST D0 needs to appear at the end of
boolExpression, after we've returned from all the functions and we have the boolean value of the expression in
D0. However the author put this inside
relation, which is a function that may or may not be called sometimes in the middle of the chain, before knowing the final value of
Can someone explain this to me? Why should the setting of the flags, i.e.
TST D0 be inside the
relation function? Why not in
Crenshaw himself explains it here (emphasis mine):<blockquote>
Now, recall that we're using a zero or a -1 in register D0 to represent a Boolean value, and also that the loop constructs expect the flags to be set to correspond. In implementing all this on the 68000, things get a a little bit tricky. Since the loop constructs operate only on the flags, it would be nice (and also quite efficient) just to set up those flags, and not load anything into D0 at all. This would be fine for the loops and branches, but remember that the relation can be used ANYWHERE a Boolean factor could be used. We may be storing its result to a Boolean variable. Since we can't know at this point how the result is going to be used, we must allow for BOTH cases. Comparing numeric data is easy enough ... the 68000 has an operation for that ... but it sets the flags, not a value. What's more, the flags will always be set the same (zero if equal, etc.), while we need the zero flag set differently for the each of the different relops. The solution is found in the 68000 instruction Scc, which sets a byte value to 0000 or FFFF (funny how that works!) depending upon the result of the specified condition. If we make the destination byte to be D0, we get the Boolean value needed. <strong>Unfortunately, there's one final complication: unlike almost every other instruction in the 68000 set, Scc does NOT reset the condition flags to match the data being stored. So we have to do one last step, which is to test D0 and set the flags to match it.</strong> It must seem to be a trip around the moon to get what we want: we first perform the test, then test the flags to set data into D0, then test D0 to set the flags again. It is sort of roundabout, but it's the most straightforward way to get the flags right, and after all it's only a couple of instructions.</blockquote>
(excerpt from <a href="http://www.epubbud.com/read.php?g=45SM7QEG&tocp=44" rel="nofollow">here</a>)