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();