Hlide problem solved (i believe)
[pspdecompiler.git] / constants.c
blobddf708f34f4972123ccf1d3f6a12fb509d79f8b0
1 /**
2 * Author: Humberto Naves (hsnaves@gmail.com)
3 */
6 #include "code.h"
7 #include "utils.h"
9 static
10 uint32 get_constant_value (struct value *val)
12 if (val->type == VAL_SSAVAR)
13 return val->val.variable->value;
14 else
15 return val->val.intval;
18 static
19 void combine_constants (struct ssavar *out, struct value *val)
21 uint32 constant;
22 if (CONST_TYPE (out->status) == VAR_STAT_NOTCONSTANT) return;
24 if (val->type == VAL_REGISTER) {
25 CONST_SETTYPE (out->status, VAR_STAT_NOTCONSTANT);
28 if (val->type == VAL_SSAVAR) {
29 if (CONST_TYPE (val->val.variable->status) == VAR_STAT_UNKCONSTANT)
30 return;
31 if (CONST_TYPE (val->val.variable->status) == VAR_STAT_NOTCONSTANT) {
32 CONST_SETTYPE (out->status, VAR_STAT_NOTCONSTANT);
33 return;
37 constant = get_constant_value (val);
38 if (CONST_TYPE (out->status) == VAR_STAT_UNKCONSTANT) {
39 CONST_SETTYPE (out->status, VAR_STAT_CONSTANT);
40 out->value = constant;
41 } else {
42 if (out->value != constant)
43 CONST_SETTYPE (out->status, VAR_STAT_NOTCONSTANT);
47 void propagate_constants (struct subroutine *sub)
49 list worklist = list_alloc (sub->code->lstpool);
50 element varel;
52 if (sub->begin->address == 0x42c) {
53 report ("coco");
56 varel = list_head (sub->ssavars);
57 while (varel) {
58 struct ssavar *var = element_getvalue (varel);
59 struct operation *op = var->def;
60 CONST_SETTYPE (var->status, VAR_STAT_UNKCONSTANT);
61 if (op->type == OP_ASM ||
62 op->type == OP_CALL ||
63 op->type == OP_START ||
64 !(IS_BIT_SET (regmask_localvars, var->name.val.intval)))
65 CONST_SETTYPE (var->status, VAR_STAT_NOTCONSTANT);
66 else {
67 var->mark = 1;
68 list_inserttail (worklist, var);
70 varel = element_next (varel);
73 while (list_size (worklist) != 0) {
74 struct ssavar *aux, *var = list_removehead (worklist);
75 struct ssavar temp;
76 struct value *val;
77 struct operation *op;
78 element opel;
80 var->mark = 0;
81 op->status &= ~OP_STAT_CONSTANT;
82 if (CONST_TYPE (var->status) == VAR_STAT_NOTCONSTANT) continue;
84 op = var->def;
85 if (op->type == OP_PHI) {
86 temp.status = VAR_STAT_UNKCONSTANT;
88 opel = list_head (op->operands);
89 while (opel) {
90 val = element_getvalue (opel);
91 combine_constants (&temp, val);
92 opel = element_next (opel);
94 } else {
95 temp.status = VAR_STAT_CONSTANT;
97 opel = list_head (op->operands);
98 while (opel) {
99 val = element_getvalue (opel);
100 if (val->type == VAL_SSAVAR) {
101 aux = val->val.variable;
102 if (CONST_TYPE (aux->status) == VAR_STAT_NOTCONSTANT) {
103 temp.status = VAR_STAT_NOTCONSTANT;
104 break;
105 } else if (CONST_TYPE (aux->status) == VAR_STAT_UNKCONSTANT)
106 temp.status = VAR_STAT_UNKCONSTANT;
108 opel = element_next (opel);
111 if (temp.status == VAR_STAT_CONSTANT) {
112 if (op->type == OP_MOVE) {
113 val = list_headvalue (op->operands);
114 temp.value = get_constant_value (val);
115 op->status |= OP_STAT_CONSTANT;
116 } else if (op->type == OP_INSTRUCTION) {
117 uint32 val1, val2;
118 switch (op->info.iop.insn) {
119 case I_ADD:
120 case I_ADDU:
121 val1 = get_constant_value (list_headvalue (op->operands));
122 val2 = get_constant_value (list_tailvalue (op->operands));
123 op->status |= OP_STAT_CONSTANT;
124 temp.value = val1 + val2;
125 break;
126 case I_OR:
127 val1 = get_constant_value (list_headvalue (op->operands));
128 val2 = get_constant_value (list_tailvalue (op->operands));
129 op->status |= OP_STAT_CONSTANT;
130 temp.value = val1 | val2;
131 break;
132 default:
133 temp.status = VAR_STAT_NOTCONSTANT;
134 break;
141 if (temp.status != CONST_TYPE (var->status)) {
142 element useel;
143 useel = list_head (var->uses);
144 while (useel) {
145 struct operation *use = element_getvalue (useel);
146 if (use->type == OP_INSTRUCTION || use->type == OP_MOVE || use->type == OP_PHI) {
147 varel = list_head (use->results);
148 while (varel) {
149 val = element_getvalue (varel);
150 if (val->type == VAL_SSAVAR) {
151 aux = val->val.variable;
152 if (!(aux->mark)) {
153 aux->mark = 1;
154 list_inserttail (worklist, aux);
157 varel = element_next (varel);
160 useel = element_next (useel);
163 CONST_SETTYPE (var->status, temp.status);
164 var->value = temp.value;
167 list_free (worklist);
170 varel = list_head (sub->ssavars);
171 while (varel) {
172 struct ssavar *var = element_getvalue (varel);
173 struct operation *op = var->def;
174 element useel;
176 if (CONST_TYPE (var->status) == VAR_STAT_CONSTANT) {
177 op->status |= OP_STAT_DEFERRED;
178 useel = list_head (var->uses);
179 while (useel) {
180 struct operation *use = element_getvalue (useel);
181 if (use->type == OP_PHI) {
182 struct value *val = list_headvalue (use->results);
183 if (val->type != VAL_SSAVAR) break;
184 if (CONST_TYPE (val->val.variable->status) != VAR_STAT_CONSTANT)
185 break;
186 } else if (use->type == OP_ASM) break;
187 useel = element_next (useel);
189 if (useel) {
190 op->status &= ~OP_STAT_DEFERRED;
194 varel = element_next (varel);