Mercurial > hg > index.cgi
comparison lwcc/cc-gencode.c @ 505:59b8c8b15bd4
Add integer shifts and fix code template errors for mul/div/mod
One needs to remove stuff from the stack after putting it there. Actually do
that in the code output for multiplication, division, and modulus.
Add integer shifting code output which is optimized for constant shift
counts but calls a routine for non-constant shift counts. Shifting by a
negative amount is a no-op. Shifting by more than the size of an integer
results in 0 (for left shifts) or -1 (for right shifts). Both negative shift
counts and shift counts larger than the base type are undefined in the C
standard so this behaviour is allowed.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sat, 26 Oct 2019 22:01:55 -0600 |
parents | 14a40f8bb4eb |
children |
comparison
equal
deleted
inserted
replaced
504:16bd8effb2f6 | 505:59b8c8b15bd4 |
---|---|
18 You should have received a copy of the GNU General Public License along with | 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/>. | 19 this program. If not, see <http://www.gnu.org/licenses/>. |
20 */ | 20 */ |
21 | 21 |
22 #include <stdio.h> | 22 #include <stdio.h> |
23 #include <stdlib.h> | |
23 #include <string.h> | 24 #include <string.h> |
24 | 25 |
25 #include <lw_alloc.h> | 26 #include <lw_alloc.h> |
26 #include <lw_string.h> | 27 #include <lw_string.h> |
27 | 28 |
34 | 35 |
35 sprintf(buf, "L%d", labelnum++); | 36 sprintf(buf, "L%d", labelnum++); |
36 return lw_strdup(buf); | 37 return lw_strdup(buf); |
37 } | 38 } |
38 | 39 |
40 void generate_code(node_t *n, FILE *output); | |
41 | |
42 void generate_code_shift(node_t *n, FILE *output, int dir) | |
43 { | |
44 generate_code(n -> children, output); | |
45 if (n -> children -> next_child -> type == NODE_CONST_INT) | |
46 { | |
47 long ival; | |
48 int i; | |
49 ival = strtol(n -> children -> next_child -> strval, NULL, 0); | |
50 if (ival <= 0) | |
51 return; | |
52 if (ival >= 16) | |
53 { | |
54 fprintf(output, "\tldd #%d\n", dir == 1 ? 0 : -1); | |
55 return; | |
56 } | |
57 if (ival >= 8) | |
58 { | |
59 if (dir == 1) | |
60 { | |
61 fprintf(output, "\ttfr b,a\n\tclrb\n"); | |
62 for (i = ival - 8; i > 0; i--) | |
63 { | |
64 fprintf(output, "\tlsla\n"); | |
65 } | |
66 } | |
67 else | |
68 { | |
69 fprintf(output, "\ttfr a,b\n\tsex\n"); | |
70 for (i = ival - 8; i > 0; i--) | |
71 { | |
72 fprintf(output, "\tasrb\n"); | |
73 } | |
74 } | |
75 return; | |
76 } | |
77 for (i = ival; i > 0; i--) | |
78 { | |
79 if (dir == 1) | |
80 { | |
81 fprintf(output, "\taslb\n\trola\n"); | |
82 } | |
83 else | |
84 { | |
85 fprintf(output, "\tasra\n\trorb\n"); | |
86 } | |
87 } | |
88 return; | |
89 } | |
90 else | |
91 { | |
92 fprintf(output, "\tpshs d\n"); | |
93 generate_code(n -> children -> next_child, output); | |
94 fprintf(output, "\tjsr ___%ssh16\n\tpuls d\n", dir == 1 ? "l" : "r"); | |
95 } | |
96 } | |
97 | |
98 | |
39 void generate_code(node_t *n, FILE *output) | 99 void generate_code(node_t *n, FILE *output) |
40 { | 100 { |
41 node_t *nn; | 101 node_t *nn; |
42 char *label1, *label2; | 102 char *label1, *label2; |
43 | 103 |
44 switch (n -> type) | 104 switch (n -> type) |
45 { | 105 { |
46 // function definition - output prologue, then statements, then epilogue | 106 // function definition - output prologue, then statements, then epilogue |
47 case NODE_FUNDEF: | 107 case NODE_FUNDEF: |
48 fprintf(output, "_%s\n", n->children->next_child->strval); | 108 fprintf(output, "\tsection .text\n\texport _%s\n_%s\n", n->children->next_child->strval, n->children->next_child->strval); |
49 generate_code(n->children->next_child->next_child->next_child, output); | 109 generate_code(n->children->next_child->next_child->next_child, output); |
50 fprintf(output, "\trts\n"); | 110 fprintf(output, "\trts\n"); |
51 break; | 111 break; |
52 | 112 |
53 case NODE_CONST_INT: | 113 case NODE_CONST_INT: |
70 | 130 |
71 case NODE_OPER_TIMES: | 131 case NODE_OPER_TIMES: |
72 generate_code(n -> children, output); | 132 generate_code(n -> children, output); |
73 fprintf(output, "\tpshs d\n"); | 133 fprintf(output, "\tpshs d\n"); |
74 generate_code(n->children->next_child, output); | 134 generate_code(n->children->next_child, output); |
75 fprintf(output, "\tjsr ___mul16i\n"); | 135 fprintf(output, "\tjsr ___mul16i\n\tpuls d\n"); |
76 break; | 136 break; |
77 | 137 |
78 case NODE_OPER_DIVIDE: | 138 case NODE_OPER_DIVIDE: |
79 generate_code(n -> children, output); | 139 generate_code(n -> children, output); |
80 fprintf(output, "\tpshs d\n"); | 140 fprintf(output, "\tpshs d\n"); |
81 generate_code(n->children->next_child, output); | 141 generate_code(n->children->next_child, output); |
82 fprintf(output, "\tjsr ___div16i\n"); | 142 fprintf(output, "\tjsr ___div16i\n\tpuls d\n"); |
83 break; | 143 break; |
84 | 144 |
85 case NODE_OPER_MOD: | 145 case NODE_OPER_MOD: |
86 generate_code(n -> children, output); | 146 generate_code(n -> children, output); |
87 fprintf(output, "\tpshs d\n"); | 147 fprintf(output, "\tpshs d\n"); |
88 generate_code(n -> children -> next_child, output); | 148 generate_code(n -> children -> next_child, output); |
89 fprintf(output, "\tjsr ___mod16i\n"); | 149 fprintf(output, "\tjsr ___mod16i\n\tpuls d\n"); |
150 break; | |
151 | |
152 case NODE_OPER_LSH: | |
153 generate_code_shift(n, output, 1); | |
154 break; | |
155 | |
156 case NODE_OPER_RSH: | |
157 generate_code_shift(n, output, 0); | |
90 break; | 158 break; |
91 | 159 |
92 case NODE_OPER_COND: | 160 case NODE_OPER_COND: |
93 label1 = generate_nextlabel(); | 161 label1 = generate_nextlabel(); |
94 label2 = generate_nextlabel(); | 162 label2 = generate_nextlabel(); |