Now my comments should be in english....
[pspdecompiler.git] / constants.c
blobb146bf46853c4dbe9786b2b8d52286eae700f6af
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 varel = list_head (sub->ssavars);
53 while (varel) {
54 struct ssavar *var = element_getvalue (varel);
55 struct operation *op = var->def;
56 CONST_SETTYPE (var->status, VAR_STAT_UNKCONSTANT);
57 if (op->type == OP_ASM ||
58 op->type == OP_CALL ||
59 op->type == OP_START ||
60 !(IS_BIT_SET (regmask_localvars, var->name.val.intval)))
61 CONST_SETTYPE (var->status, VAR_STAT_NOTCONSTANT);
62 else {
63 var->mark = 1;
64 list_inserttail (worklist, var);
66 varel = element_next (varel);
69 while (list_size (worklist) != 0) {
70 struct ssavar *aux, *var = list_removehead (worklist);
71 struct ssavar temp;
72 struct value *val;
73 struct operation *op;
74 element opel;
76 var->mark = 0;
77 if (CONST_TYPE (var->status) == VAR_STAT_NOTCONSTANT) continue;
79 op = var->def;
80 if (op->type == OP_PHI) {
81 temp.status = VAR_STAT_UNKCONSTANT;
83 opel = list_head (op->operands);
84 while (opel) {
85 val = element_getvalue (opel);
86 combine_constants (&temp, val);
87 opel = element_next (opel);
89 } else {
90 temp.status = VAR_STAT_CONSTANT;
92 opel = list_head (op->operands);
93 while (opel) {
94 val = element_getvalue (opel);
95 if (val->type == VAL_SSAVAR) {
96 aux = val->val.variable;
97 if (CONST_TYPE (aux->status) == VAR_STAT_NOTCONSTANT) {
98 temp.status = VAR_STAT_NOTCONSTANT;
99 break;
100 } else if (CONST_TYPE (aux->status) == VAR_STAT_UNKCONSTANT)
101 temp.status = VAR_STAT_UNKCONSTANT;
103 opel = element_next (opel);
106 if (temp.status == VAR_STAT_CONSTANT) {
107 if (op->type == OP_MOVE) {
108 val = list_headvalue (op->operands);
109 temp.value = get_constant_value (val);
110 op->status |= OP_STAT_CONSTANT;
111 } else if (op->type == OP_INSTRUCTION) {
112 uint32 val1, val2;
113 switch (op->info.iop.insn) {
114 case I_ADD:
115 case I_ADDU:
116 val1 = get_constant_value (list_headvalue (op->operands));
117 val2 = get_constant_value (list_tailvalue (op->operands));
118 op->status |= OP_STAT_CONSTANT;
119 temp.value = val1 + val2;
120 break;
121 case I_OR:
122 val1 = get_constant_value (list_headvalue (op->operands));
123 val2 = get_constant_value (list_tailvalue (op->operands));
124 op->status |= OP_STAT_CONSTANT;
125 temp.value = val1 | val2;
126 break;
127 default:
128 temp.status = VAR_STAT_NOTCONSTANT;
129 break;
136 if (temp.status != CONST_TYPE (var->status)) {
137 element useel;
138 useel = list_head (var->uses);
139 while (useel) {
140 struct operation *use = element_getvalue (useel);
141 if (use->type == OP_INSTRUCTION || use->type == OP_MOVE || use->type == OP_PHI) {
142 varel = list_head (use->results);
143 while (varel) {
144 val = element_getvalue (varel);
145 if (val->type == VAL_SSAVAR) {
146 aux = val->val.variable;
147 if (!(aux->mark)) {
148 aux->mark = 1;
149 list_inserttail (worklist, aux);
152 varel = element_next (varel);
155 useel = element_next (useel);
158 CONST_SETTYPE (var->status, temp.status);
159 var->value = temp.value;
162 list_free (worklist);
165 varel = list_head (sub->ssavars);
166 while (varel) {
167 struct ssavar *var = element_getvalue (varel);
168 struct operation *op = var->def;
169 element useel;
171 if (CONST_TYPE (var->status) == VAR_STAT_CONSTANT) {
172 op->status |= OP_STAT_DEFERRED;
173 useel = list_head (var->uses);
174 while (useel) {
175 struct operation *use = element_getvalue (useel);
176 if (use->type == OP_PHI) {
177 struct value *val = list_headvalue (use->results);
178 if (val->type != VAL_SSAVAR) break;
179 if (CONST_TYPE (val->val.variable->status) != VAR_STAT_CONSTANT)
180 break;
181 } else if (use->type == OP_ASM) break;
182 useel = element_next (useel);
184 if (useel) {
185 op->status &= ~OP_STAT_DEFERRED;
189 varel = element_next (varel);