Mercurial > hg > index.cgi
annotate lwcc/cc-gencode.c @ 502:14a40f8bb4eb
Add various operators to lwcc
Add various binary and ternary operators to lwcc, but only those which can
work with constant operands. Seems like variables are probably required
next.
author | William Astle <lost@l-w.ca> |
---|---|
date | Wed, 25 Sep 2019 20:23:49 -0600 |
parents | f3e9732973f1 |
children | 59b8c8b15bd4 |
rev | line source |
---|---|
499 | 1 /* |
2 lwcc/cc-gencode.c | |
3 | |
4 Copyright © 2019 William Astle | |
5 | |
6 This file is part of LWTOOLS. | |
7 | |
8 LWTOOLS is free software: you can redistribute it and/or modify it under the | |
9 terms of the GNU General Public License as published by the Free Software | |
10 Foundation, either version 3 of the License, or (at your option) any later | |
11 version. | |
12 | |
13 This program is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 more details. | |
17 | |
18 You should have received a copy of the GNU General Public License along with | |
19 this program. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
22 #include <stdio.h> | |
23 #include <string.h> | |
24 | |
25 #include <lw_alloc.h> | |
26 #include <lw_string.h> | |
27 | |
28 #include "tree.h" | |
29 | |
502 | 30 char *generate_nextlabel(void) |
31 { | |
32 static int labelnum = 0; | |
33 char buf[16]; | |
34 | |
35 sprintf(buf, "L%d", labelnum++); | |
36 return lw_strdup(buf); | |
37 } | |
38 | |
499 | 39 void generate_code(node_t *n, FILE *output) |
40 { | |
41 node_t *nn; | |
502 | 42 char *label1, *label2; |
43 | |
499 | 44 switch (n -> type) |
45 { | |
46 // function definition - output prologue, then statements, then epilogue | |
47 case NODE_FUNDEF: | |
48 fprintf(output, "_%s\n", n->children->next_child->strval); | |
49 generate_code(n->children->next_child->next_child->next_child, output); | |
50 fprintf(output, "\trts\n"); | |
51 break; | |
52 | |
53 case NODE_CONST_INT: | |
54 fprintf(output, "\tldd #%s\n", n->strval); | |
55 break; | |
56 | |
501
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
57 case NODE_OPER_PLUS: |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
58 generate_code(n->children, output); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
59 fprintf(output, "\tpshs d\n"); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
60 generate_code(n->children->next_child, output); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
61 fprintf(output, "\taddd ,s++\n"); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
62 break; |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
63 |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
64 case NODE_OPER_MINUS: |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
65 generate_code(n->children, output); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
66 fprintf(output, "\tpshs d,x\n"); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
67 generate_code(n->children->next_child, output); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
68 fprintf(output, "\tstd 2,s\n\tpuls d\n\tsubd ,s++\n"); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
69 break; |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
70 |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
71 case NODE_OPER_TIMES: |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
72 generate_code(n -> children, output); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
73 fprintf(output, "\tpshs d\n"); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
74 generate_code(n->children->next_child, output); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
75 fprintf(output, "\tjsr ___mul16i\n"); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
76 break; |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
77 |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
78 case NODE_OPER_DIVIDE: |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
79 generate_code(n -> children, output); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
80 fprintf(output, "\tpshs d\n"); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
81 generate_code(n->children->next_child, output); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
82 fprintf(output, "\tjsr ___div16i\n"); |
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
83 break; |
502 | 84 |
85 case NODE_OPER_MOD: | |
86 generate_code(n -> children, output); | |
87 fprintf(output, "\tpshs d\n"); | |
88 generate_code(n -> children -> next_child, output); | |
89 fprintf(output, "\tjsr ___mod16i\n"); | |
90 break; | |
501
f3e9732973f1
Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents:
499
diff
changeset
|
91 |
502 | 92 case NODE_OPER_COND: |
93 label1 = generate_nextlabel(); | |
94 label2 = generate_nextlabel(); | |
95 generate_code(n -> children, output); | |
96 fprintf(output, "\tsubd #0\n\tbeq %s\n", label1); | |
97 generate_code(n -> children -> next_child, output); | |
98 fprintf(output, "\tbra %s\n%s\n", label2, label1); | |
99 generate_code(n -> children -> next_child -> next_child, output); | |
100 fprintf(output, "%s\n", label2); | |
101 lw_free(label1); | |
102 lw_free(label2); | |
103 break; | |
104 | |
105 case NODE_OPER_COMMA: | |
106 generate_code(n -> children, output); | |
107 generate_code(n -> children -> next_child, output); | |
108 break; | |
109 | |
110 case NODE_OPER_BWAND: | |
111 generate_code(n -> children, output); | |
112 fprintf(output, "\tpshs d\n"); | |
113 generate_code(n -> children -> next_child, output); | |
114 fprintf(output, "\tandb 1,s\n\tanda ,s++\n"); | |
115 break; | |
116 | |
117 case NODE_OPER_BWOR: | |
118 generate_code(n -> children, output); | |
119 fprintf(output, "\tpshs d\n"); | |
120 generate_code(n -> children -> next_child, output); | |
121 fprintf(output, "\torb 1,s\n\tora ,s++\n"); | |
122 break; | |
123 | |
124 case NODE_OPER_BWXOR: | |
125 generate_code(n -> children, output); | |
126 fprintf(output, "\tpshs d\n"); | |
127 generate_code(n -> children -> next_child, output); | |
128 fprintf(output, "\teorb 1,s\n\teora ,s++\n"); | |
129 break; | |
130 | |
131 case NODE_OPER_BAND: | |
132 label1 = generate_nextlabel(); | |
133 generate_code(n -> children, output); | |
134 fprintf(output, "\tsubd #0\n\tbeq %s\n", label1); | |
135 generate_code(n -> children -> next_child, output); | |
136 fprintf(output, "\tsubd #0\n\tbeq %s\n\tldd #1\n%s\n", label1, label1); | |
137 lw_free(label1); | |
138 break; | |
139 | |
140 case NODE_OPER_BOR: | |
141 label1 = generate_nextlabel(); | |
142 label2 = generate_nextlabel(); | |
143 generate_code(n -> children, output); | |
144 fprintf(output, "\tsubd #0\n\tbne %s\n", label1); | |
145 generate_code(n -> children -> next_child, output); | |
146 fprintf(output, "\tsubd #0\n\tbeq %s\n%s\tldd #1\n%s\n", label2, label1, label2); | |
147 lw_free(label1); | |
148 lw_free(label2); | |
149 break; | |
150 | |
151 case NODE_OPER_NE: | |
152 case NODE_OPER_EQ: | |
153 case NODE_OPER_LT: | |
154 case NODE_OPER_GT: | |
155 case NODE_OPER_LE: | |
156 case NODE_OPER_GE: | |
157 generate_code(n -> children, output); | |
158 fprintf(output, "\tpshs d\n"); | |
159 generate_code(n -> children -> next_child, output); | |
160 fprintf(output, "\tsubd ,s++\n"); | |
161 label1 = generate_nextlabel(); | |
162 label2 = generate_nextlabel(); | |
163 fprintf(output, "\t%s %s\n", ( | |
164 (n -> type == NODE_OPER_NE ? "bne" : | |
165 (n -> type == NODE_OPER_EQ ? "beq" : | |
166 (n -> type == NODE_OPER_LT ? "bge" : | |
167 (n -> type == NODE_OPER_GT ? "ble" : | |
168 (n -> type == NODE_OPER_LE ? "bgt" : | |
169 (n -> type == NODE_OPER_GE ? "blt" : | |
170 "foobar")))))) | |
171 ), label1); | |
172 fprintf(output, "\tldd #0\n\tbra %s\n%s\tldd #1\n%s\n", label2, label1, label2); | |
173 lw_free(label1); | |
174 lw_free(label2); | |
175 break; | |
176 | |
499 | 177 default: |
178 for (nn = n -> children; nn; nn = nn -> next_child) | |
179 generate_code(nn, output); | |
180 break; | |
181 } | |
182 } |