summaryrefslogtreecommitdiff
path: root/miniany/cc.c
diff options
context:
space:
mode:
Diffstat (limited to 'miniany/cc.c')
-rw-r--r--miniany/cc.c158
1 files changed, 155 insertions, 3 deletions
diff --git a/miniany/cc.c b/miniany/cc.c
index 6f4f0a8..01472c9 100644
--- a/miniany/cc.c
+++ b/miniany/cc.c
@@ -13,7 +13,15 @@ enum {
S_STAR,
S_SLASH,
S_SEMICOLON,
+ S_LPAREN,
+ S_RPAREN,
+ S_ASSIGN,
S_EQUALS,
+ S_NOT_EQUALS,
+ S_LESS,
+ S_LESS_OR_EQUALS,
+ S_MORE,
+ S_MORE_OR_EQUALS,
S_INT = 10,
S_PUTINT,
S_IDENT = 20,
@@ -214,7 +222,43 @@ int getToken( struct Scanner *scanner )
scanner->token = S_SEMICOLON;
break;
case '=':
- scanner->token = S_EQUALS;
+ c = getChar( scanner );
+ if( c == '=' ) {
+ scanner->token = S_EQUALS;
+ } else {
+ pushBack( scanner );
+ scanner->token = S_ASSIGN;
+ }
+ break;
+ case '!':
+ c = getChar( scanner );
+ if( c == '=' ) {
+ scanner->token = S_NOT_EQUALS;
+ } else {
+ pushBack( scanner );
+ }
+ break;
+ case '<':
+ c = getChar( scanner );
+ if( c == '=' ) {
+ scanner->token = S_LESS_OR_EQUALS;
+ } else {
+ scanner->token = S_LESS;
+ }
+ break;
+ case '>':
+ c = getChar( scanner );
+ if( c == '=' ) {
+ scanner->token = S_MORE_OR_EQUALS;
+ } else {
+ scanner->token = S_MORE;
+ }
+ break;
+ case '(':
+ scanner->token = S_LPAREN;
+ break;
+ case ')':
+ scanner->token = S_RPAREN;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
@@ -351,6 +395,12 @@ enum {
A_MULTIPLY,
A_DIVIDE,
A_ASSIGN,
+ A_EQUALS,
+ A_NOT_EQUALS,
+ A_LESS,
+ A_LESS_OR_EQUALS,
+ A_MORE,
+ A_MORE_OR_EQUALS,
A_ERR = 99
};
@@ -480,6 +530,32 @@ void putreg( struct Generator *generator, int reg )
putstring( generator->regName[reg] );
}
+void putlow8reg( struct Generator *generator, int reg )
+{
+ switch( reg ) {
+ case EAX:
+ putstring( "al" );
+ break;
+ case EBX:
+ putstring( "bl" );
+ break;
+ case ECX:
+ putstring( "cl" );
+ break;
+ case EDX:
+ putstring( "dl" );
+ break;
+ default:
+ scannerPrintErrorHeader( generator->scanner );
+ putstring( "error using low 8-bit subreguster of reguster '" );
+ putstring( generator->regName[reg] );
+ putstring( "'" );
+ putnl( );
+ exit( EXIT_FAILURE );
+ }
+}
+
+
void genAddGlob( struct Generator *generator, char *ident )
{
putstring( ident );
@@ -747,6 +823,26 @@ int genDiv( struct Generator *generator, int leftreg, int rightreg )
return reg;
}
+int genCompare( char *op, struct Generator *generator, int leftreg, int rightreg )
+{
+ putstring( "cmp " );
+ putreg( generator, leftreg );
+ putstring( ", " );
+ putreg( generator, rightreg );
+ putnl( );
+ putstring( op );
+ putchar( ' ' );
+ putlow8reg( generator, leftreg );
+ putnl( );
+ putstring( "and " );
+ putreg( generator, leftreg );
+ putstring( ", $FF" );
+ putnl( );
+ genFreeReg( generator, rightreg );
+
+ return leftreg;
+}
+
int generateFromAST( struct Generator *generator, struct ASTnode *node, int inreg )
{
int leftreg, rightreg, reg;
@@ -785,6 +881,24 @@ int generateFromAST( struct Generator *generator, struct ASTnode *node, int inre
case A_ASSIGN:
reg = inreg;
break;
+ case A_EQUALS:
+ reg = genCompare( "sete", generator, leftreg, rightreg );
+ break;
+ case A_NOT_EQUALS:
+ reg = genCompare( "setne", generator, leftreg, rightreg );
+ break;
+ case A_LESS_OR_EQUALS:
+ reg = genCompare( "setle", generator, leftreg, rightreg );
+ break;
+ case A_LESS:
+ reg = genCompare( "setl", generator, leftreg, rightreg );
+ break;
+ case A_MORE:
+ reg = genCompare( "setg", generator, leftreg, rightreg );
+ break;
+ case A_MORE_OR_EQUALS:
+ reg = genCompare( "setge", generator, leftreg, rightreg );
+ break;
default:
putint( node->op );
putstring( "?" );
@@ -897,6 +1011,30 @@ int parserTokenToOperator( struct Parser *parser, int token )
case S_MINUS:
op = A_SUBTRACT;
break;
+
+ case S_EQUALS:
+ op = A_EQUALS;
+ break;
+
+ case S_NOT_EQUALS:
+ op = A_NOT_EQUALS;
+ break;
+
+ case S_LESS:
+ op = A_LESS;
+ break;
+
+ case S_LESS_OR_EQUALS:
+ op = A_LESS_OR_EQUALS;
+ break;
+
+ case S_MORE:
+ op = A_MORE;
+ break;
+
+ case S_MORE_OR_EQUALS:
+ op = A_MORE_OR_EQUALS;
+ break;
default:
scannerPrintErrorHeader( parser->scanner );
@@ -915,6 +1053,18 @@ int parserOperatorPrecedence( struct Parser *parser, int operator )
precedence = 0;
switch( operator ) {
+ case A_LESS:
+ case A_LESS_OR_EQUALS:
+ case A_MORE:
+ case A_MORE_OR_EQUALS:
+ precedence = 4;
+ break;
+
+ case A_EQUALS:
+ case A_NOT_EQUALS:
+ precedence = 3;
+ break;
+
case A_MULTIPLY:
case A_DIVIDE:
precedence = 2;
@@ -973,7 +1123,7 @@ struct ASTnode *parseExpression( struct Parser *parser, int level )
}
parser->token = getToken( parser->scanner );
- if( parser->token == S_EOI || parser->token == S_SEMICOLON ) {
+ if( parser->token == S_EOI || parser->token == S_SEMICOLON || parser->token == S_RPAREN ) {
return left;
}
@@ -1032,7 +1182,7 @@ void parseAssignment( struct Compiler *compiler )
exit( EXIT_FAILURE );
}
right = createASTleafSym( A_LVIDENT, sym );
- parserExpect( parser, S_EQUALS, "=" );
+ parserExpect( parser, S_ASSIGN, "=" );
left = parseExpression( parser, 0 );
parserExpect( parser, S_SEMICOLON, ";" );
@@ -1049,7 +1199,9 @@ void parsePutint( struct Compiler *compiler )
parser = compiler->parser;
parserExpect( parser, S_PUTINT, "putint" );
+ parserExpect( parser, S_LPAREN, "(" );
node = parseExpression( parser, 0 );
+ parserExpect( parser, S_RPAREN, ")" );
parserExpect( parser, S_SEMICOLON, ";" );
generateFromAST( compiler->generator, node, NOREG );
putstring( "call putint" ); putnl( );