Com o autor
[pspdecompiler.git] / constants.c
blobbb71ecefdfbc102da2d6361c1864bc833ca70470
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->info;
14 else
15 return val->val.intval;
18 static
19 void combine_constants (struct ssavar *out, struct value *val)
21 uint32 constant;
22 if (out->type == SSAVAR_UNK) return;
24 if (val->type == VAL_REGISTER) {
25 out->type = SSAVAR_UNK;
26 return;
29 if (val->type == VAL_SSAVAR) {
30 if (val->val.variable->type == SSAVAR_CONSTANTUNK)
31 return;
32 if (val->val.variable->type == SSAVAR_UNK) {
33 out->type = SSAVAR_UNK;
34 return;
38 constant = get_constant_value (val);
39 if (out->type == SSAVAR_CONSTANTUNK) {
40 out->type = SSAVAR_CONSTANT;
41 out->info = constant;
42 } else {
43 if (out->info != constant)
44 out->type = SSAVAR_UNK;
48 void propagate_constants (struct subroutine *sub)
50 list worklist = list_alloc (sub->code->lstpool);
51 element varel;
53 varel = list_head (sub->ssavars);
54 while (varel) {
55 struct ssavar *var = element_getvalue (varel);
56 var->type = SSAVAR_CONSTANTUNK;
57 if (var->def->type == OP_ASM ||
58 var->def->type == OP_CALL ||
59 var->def->type == OP_START ||
60 !(IS_BIT_SET (regmask_localvars, var->name.val.intval)))
61 var->type = SSAVAR_UNK;
62 else
63 list_inserttail (worklist, var);
64 varel = element_next (varel);
67 while (list_size (worklist) != 0) {
68 struct ssavar *var = list_removehead (worklist);
69 struct ssavar temp;
70 struct value *val;
71 element opel;
73 if (var->type == SSAVAR_UNK) continue;
75 if (var->def->type == OP_PHI) {
76 temp.type = SSAVAR_CONSTANTUNK;
78 opel = list_head (var->def->operands);
79 while (opel) {
80 val = element_getvalue (opel);
81 combine_constants (&temp, val);
82 opel = element_next (opel);
84 } else {
85 temp.type = SSAVAR_CONSTANT;
87 opel = list_head (var->def->operands);
88 while (opel) {
89 val = element_getvalue (opel);
90 if (val->type == VAL_CONSTANT) {
91 } else if (val->type == VAL_SSAVAR) {
92 if (val->val.variable->type == SSAVAR_UNK)
93 temp.type = SSAVAR_UNK;
94 else if (val->val.variable->type == SSAVAR_CONSTANTUNK &&
95 temp.type != SSAVAR_UNK)
96 temp.type = SSAVAR_CONSTANTUNK;
98 opel = element_next (opel);
101 if (temp.type == SSAVAR_CONSTANT) {
102 if (var->def->type == OP_MOVE) {
103 val = list_headvalue (var->def->operands);
104 temp.info = get_constant_value (val);
105 var->def->status |= OP_STAT_DEFERRED;
106 } else if (var->def->type == OP_INSTRUCTION) {
107 uint32 val1, val2;
108 switch (var->def->info.iop.insn) {
109 case I_ADD:
110 case I_ADDU:
111 val1 = get_constant_value (list_headvalue (var->def->operands));
112 val2 = get_constant_value (list_tailvalue (var->def->operands));
113 temp.info = val1 + val2;
114 var->def->status |= OP_STAT_DEFERRED;
115 break;
116 case I_OR:
117 val1 = get_constant_value (list_headvalue (var->def->operands));
118 val2 = get_constant_value (list_tailvalue (var->def->operands));
119 temp.info = val1 | val2;
120 var->def->status |= OP_STAT_DEFERRED;
121 break;
122 default:
123 temp.type = SSAVAR_UNK;
124 break;
131 if (temp.type != var->type) {
132 element useel;
133 useel = list_head (var->uses);
134 while (useel) {
135 struct operation *use = element_getvalue (useel);
136 varel = list_head (use->results);
137 while (varel) {
138 val = element_getvalue (varel);
139 if (val->type == VAL_SSAVAR)
140 list_inserttail (worklist, val->val.variable);
141 varel = element_next (varel);
143 useel = element_next (useel);
146 var->type = temp.type;
147 var->info = temp.info;
151 list_free (worklist);