1
2 /*---------------------------------------------------------------*/
3 /*--- begin host_generic_regs.c ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2004-2012 OpenWorks LLP
11 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
34 */
35
36 #include "libvex_basictypes.h"
37 #include "libvex.h"
38
39 #include "main_util.h"
40 #include "host_generic_regs.h"
41
42
ppHRegClass(HRegClass hrc)43 void ppHRegClass ( HRegClass hrc )
44 {
45 switch (hrc) {
46 case HRcInt32: vex_printf("HRcInt32"); break;
47 case HRcInt64: vex_printf("HRcInt64"); break;
48 case HRcFlt32: vex_printf("HRcFlt32"); break;
49 case HRcFlt64: vex_printf("HRcFlt64"); break;
50 case HRcVec64: vex_printf("HRcVec64"); break;
51 case HRcVec128: vex_printf("HRcVec128"); break;
52 default: vpanic("ppHRegClass");
53 }
54 }
55
56 /* Generic printing for registers. */
ppHReg(HReg r)57 void ppHReg ( HReg r )
58 {
59 HChar* maybe_v = hregIsVirtual(r) ? "v" : "";
60 Int regNo = hregNumber(r);
61 switch (hregClass(r)) {
62 case HRcInt32: vex_printf("%%%sr%d", maybe_v, regNo); return;
63 case HRcInt64: vex_printf("%%%sR%d", maybe_v, regNo); return;
64 case HRcFlt32: vex_printf("%%%sF%d", maybe_v, regNo); return;
65 case HRcFlt64: vex_printf("%%%sD%d", maybe_v, regNo); return;
66 case HRcVec64: vex_printf("%%%sv%d", maybe_v, regNo); return;
67 case HRcVec128: vex_printf("%%%sV%d", maybe_v, regNo); return;
68 default: vpanic("ppHReg");
69 }
70 }
71
72
73 /*---------------------------------------------------------*/
74 /*--- Helpers for recording reg usage (for reg-alloc) ---*/
75 /*---------------------------------------------------------*/
76
ppHRegUsage(HRegUsage * tab)77 void ppHRegUsage ( HRegUsage* tab )
78 {
79 Int i;
80 HChar* str;
81 vex_printf("HRegUsage {\n");
82 for (i = 0; i < tab->n_used; i++) {
83 switch (tab->mode[i]) {
84 case HRmRead: str = "Read "; break;
85 case HRmWrite: str = "Write "; break;
86 case HRmModify: str = "Modify "; break;
87 default: vpanic("ppHRegUsage");
88 }
89 vex_printf(" %s ", str);
90 ppHReg(tab->hreg[i]);
91 vex_printf("\n");
92 }
93 vex_printf("}\n");
94 }
95
96
97 /* Add a register to a usage table. Combine incoming read uses with
98 existing write uses into a modify use, and vice versa. Do not
99 create duplicate entries -- each reg should only be mentioned once.
100 */
addHRegUse(HRegUsage * tab,HRegMode mode,HReg reg)101 void addHRegUse ( HRegUsage* tab, HRegMode mode, HReg reg )
102 {
103 Int i;
104 /* Find it ... */
105 for (i = 0; i < tab->n_used; i++)
106 if (tab->hreg[i] == reg)
107 break;
108 if (i == tab->n_used) {
109 /* Not found, add new entry. */
110 vassert(tab->n_used < N_HREG_USAGE);
111 tab->hreg[tab->n_used] = reg;
112 tab->mode[tab->n_used] = mode;
113 tab->n_used++;
114 } else {
115 /* Found: combine or ignore. */
116 /* This is a greatest-lower-bound operation in the poset:
117
118 R W
119 \ /
120 M
121
122 Need to do: tab->mode[i] = GLB(tab->mode, mode). In this
123 case very simple -- if tab->mode[i] != mode then result must
124 be M.
125 */
126 if (tab->mode[i] == mode) {
127 /* duplicate, ignore */
128 } else {
129 tab->mode[i] = HRmModify;
130 }
131 }
132 }
133
134
135 /*---------------------------------------------------------*/
136 /*--- Indicating register remappings (for reg-alloc) ---*/
137 /*---------------------------------------------------------*/
138
ppHRegRemap(HRegRemap * map)139 void ppHRegRemap ( HRegRemap* map )
140 {
141 Int i;
142 vex_printf("HRegRemap {\n");
143 for (i = 0; i < map->n_used; i++) {
144 vex_printf(" ");
145 ppHReg(map->orig[i]);
146 vex_printf(" --> ");
147 ppHReg(map->replacement[i]);
148 vex_printf("\n");
149 }
150 vex_printf("}\n");
151 }
152
153
initHRegRemap(HRegRemap * map)154 void initHRegRemap ( HRegRemap* map )
155 {
156 map->n_used = 0;
157 }
158
159
addToHRegRemap(HRegRemap * map,HReg orig,HReg replacement)160 void addToHRegRemap ( HRegRemap* map, HReg orig, HReg replacement )
161 {
162 Int i;
163 for (i = 0; i < map->n_used; i++)
164 if (map->orig[i] == orig)
165 vpanic("addToHRegMap: duplicate entry");
166 if (!hregIsVirtual(orig))
167 vpanic("addToHRegMap: orig is not a vreg");
168 if (hregIsVirtual(replacement))
169 vpanic("addToHRegMap: replacement is a vreg");
170
171 vassert(map->n_used+1 < N_HREG_REMAP);
172 map->orig[map->n_used] = orig;
173 map->replacement[map->n_used] = replacement;
174 map->n_used++;
175 }
176
177
lookupHRegRemap(HRegRemap * map,HReg orig)178 HReg lookupHRegRemap ( HRegRemap* map, HReg orig )
179 {
180 Int i;
181 if (!hregIsVirtual(orig))
182 return orig;
183 for (i = 0; i < map->n_used; i++)
184 if (map->orig[i] == orig)
185 return map->replacement[i];
186 vpanic("lookupHRegRemap: not found");
187 }
188
189 /*---------------------------------------------------------*/
190 /*--- Abstract instructions ---*/
191 /*---------------------------------------------------------*/
192
newHInstrArray(void)193 HInstrArray* newHInstrArray ( void )
194 {
195 HInstrArray* ha = LibVEX_Alloc(sizeof(HInstrArray));
196 ha->arr_size = 4;
197 ha->arr_used = 0;
198 ha->arr = LibVEX_Alloc(ha->arr_size * sizeof(HInstr*));
199 ha->n_vregs = 0;
200 return ha;
201 }
202
addHInstr(HInstrArray * ha,HInstr * instr)203 void addHInstr ( HInstrArray* ha, HInstr* instr )
204 {
205 vassert(ha->arr_used <= ha->arr_size);
206 if (ha->arr_used < ha->arr_size) {
207 ha->arr[ha->arr_used] = instr;
208 ha->arr_used++;
209 } else {
210 Int i;
211 HInstr** arr2 = LibVEX_Alloc(ha->arr_size * 2 * sizeof(HInstr*));
212 for (i = 0; i < ha->arr_size; i++)
213 arr2[i] = ha->arr[i];
214 ha->arr_size *= 2;
215 ha->arr = arr2;
216 addHInstr(ha, instr);
217 }
218 }
219
220
221 /*---------------------------------------------------------------*/
222 /*--- end host_generic_regs.c ---*/
223 /*---------------------------------------------------------------*/
224