Passo intermediario, ainda falta um longo caminho
[pspdecompiler.git] / constants.c
blob3bc0ba11cec089d69258d507987a36d3432f6d36
3 #include "code.h"
4 #include "utils.h"
6 static
7 uint32 get_constant_value (struct value *val)
9 if (val->type == VAL_SSAVAR)
10 return val->val.variable->info;
11 else
12 return val->val.intval;
15 static
16 void combine_constants (struct ssavar *out, struct value *val)
18 uint32 constant;
19 if (out->type == SSAVAR_UNK) return;
21 if (val->type == VAL_REGISTER) {
22 out->type = SSAVAR_UNK;
23 return;
26 if (val->type == VAL_SSAVAR) {
27 if (val->val.variable->type == SSAVAR_CONSTANTUNK)
28 return;
29 if (val->val.variable->type == SSAVAR_UNK) {
30 out->type = SSAVAR_UNK;
31 return;
35 constant = get_constant_value (val);
36 if (out->type == SSAVAR_CONSTANTUNK) {
37 out->type = SSAVAR_CONSTANT;
38 out->info = constant;
39 } else {
40 if (out->info != constant)
41 out->type = SSAVAR_UNK;
45 void propagate_constants (struct subroutine *sub)
47 list worklist = list_alloc (sub->code->lstpool);
48 element varel;
50 varel = list_head (sub->ssavars);
51 while (varel) {
52 struct ssavar *var = element_getvalue (varel);
53 var->type = SSAVAR_CONSTANTUNK;
54 if (var->def->type == OP_ASM ||
55 var->def->type == OP_CALL ||
56 var->def->type == OP_START ||
57 !(IS_BIT_SET (regmask_localvars, var->name.val.intval)))
58 var->type = SSAVAR_UNK;
59 else
60 list_inserttail (worklist, var);
61 varel = element_next (varel);
64 while (list_size (worklist) != 0) {
65 struct ssavar *var = list_removehead (worklist);
66 struct ssavar temp;
67 struct value *val;
68 element opel;
70 if (var->type == SSAVAR_UNK) continue;
72 if (var->def->type == OP_PHI) {
73 temp.type = SSAVAR_CONSTANTUNK;
75 opel = list_head (var->def->operands);
76 while (opel) {
77 val = element_getvalue (opel);
78 combine_constants (&temp, val);
79 opel = element_next (opel);
81 } else {
82 temp.type = SSAVAR_CONSTANT;
84 opel = list_head (var->def->operands);
85 while (opel) {
86 val = element_getvalue (opel);
87 if (val->type == VAL_CONSTANT) {
88 } else if (val->type == VAL_SSAVAR) {
89 if (val->val.variable->type == SSAVAR_UNK)
90 temp.type = SSAVAR_UNK;
91 else if (val->val.variable->type == SSAVAR_CONSTANTUNK &&
92 temp.type != SSAVAR_UNK)
93 temp.type = SSAVAR_CONSTANTUNK;
95 opel = element_next (opel);
98 if (temp.type == SSAVAR_CONSTANT) {
99 if (var->def->type == OP_MOVE) {
100 val = list_headvalue (var->def->operands);
101 temp.info = get_constant_value (val);
102 var->def->status |= OPERATION_DEFERRED;
103 } else if (var->def->type == OP_INSTRUCTION) {
104 uint32 val1, val2;
105 switch (var->def->info.iop.insn) {
106 case I_ADD:
107 case I_ADDU:
108 val1 = get_constant_value (list_headvalue (var->def->operands));
109 val2 = get_constant_value (list_tailvalue (var->def->operands));
110 temp.info = val1 + val2;
111 var->def->status |= OPERATION_DEFERRED;
112 break;
113 case I_OR:
114 val1 = get_constant_value (list_headvalue (var->def->operands));
115 val2 = get_constant_value (list_tailvalue (var->def->operands));
116 temp.info = val1 | val2;
117 var->def->status |= OPERATION_DEFERRED;
118 break;
119 default:
120 temp.type = SSAVAR_UNK;
121 break;
128 if (temp.type != var->type) {
129 element useel;
130 useel = list_head (var->uses);
131 while (useel) {
132 struct operation *use = element_getvalue (useel);
133 varel = list_head (use->results);
134 while (varel) {
135 val = element_getvalue (varel);
136 if (val->type == VAL_SSAVAR)
137 list_inserttail (worklist, val->val.variable);
138 varel = element_next (varel);
140 useel = element_next (useel);
143 var->type = temp.type;
144 var->info = temp.info;
148 list_free (worklist);