|
|
1.1 root 1: /* $Id: sparc-rc-cc.c,v 1.2 2009/08/28 01:41:45 fredette Exp $ */
2:
3: /* ic/sparc/sparc-rc-cc.c - SPARC recode condition code support: */
4:
5: /*
6: * Copyright (c) 2008 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #if TME_SPARC_RECODE_SIZE(ic) == TME_RECODE_SIZE_32
37:
38: _TME_RCSID("$Id: sparc-rc-cc.c,v 1.2 2009/08/28 01:41:45 fredette Exp $");
39:
40: /* macros: */
41:
42: /* this converts sparc64 icc flags into the current architecture's icc
43: flags: */
44: #define TME_SPARC_ICC(ccr_icc) \
45: ((ccr_icc) \
46: * (((TME_SPARC_VERSION(ic) < 9) \
47: * (TME_SPARC32_PSR_ICC \
48: / TME_SPARC64_CCR_ICC)) \
49: + (TME_SPARC_VERSION(ic) >= 9)))
50:
51: #define TME_SPARC_RECODE_CCR_NEED(insn_class, insn_size, size) \
52: ((((insn_class == TME_RECODE_INSN_CLASS_ADDITIVE) \
53: * ((TME_SPARC64_CCR_ICC_C \
54: * (TME_RECODE_FLAG_NEED(insn_class, insn_size, \
55: TME_RECODE_COND_C, size) \
56: != 0)) \
57: + (TME_SPARC64_CCR_ICC_V \
58: * (TME_RECODE_FLAG_NEED(insn_class, insn_size, \
59: TME_RECODE_COND_V, size) \
60: != 0)))) \
61: + (TME_SPARC64_CCR_ICC_Z \
62: * (TME_RECODE_FLAG_NEED(insn_class, insn_size, \
63: TME_RECODE_COND_Z, size) \
64: != 0)) \
65: + (TME_SPARC64_CCR_ICC_N \
66: * (TME_RECODE_FLAG_NEED(insn_class, insn_size, \
67: TME_RECODE_COND_N, size) \
68: != 0))) \
69: * ((TME_SPARC64_CCR_XCC \
70: / TME_SPARC64_CCR_ICC) \
71: * (size > TME_RECODE_SIZE_32)))
72:
73: /* this macro gives the %icc and %xcc N and Z flags: */
74: #define TME_SPARC_RECODE_CCR_N_Z(dst, ccr_need) \
75: (0 \
76: + ((((tme_uint32_t) (dst)) == 0) \
77: * ((ccr_need) & TME_SPARC64_CCR_ICC_Z)) \
78: + ((((tme_int32_t) (dst)) < 0) \
79: * ((ccr_need) & TME_SPARC64_CCR_ICC_N)) \
80: + ((((tme_sparc_ireg_t) (dst)) == 0) \
81: * ((ccr_need) & TME_SPARC64_CCR_XCC_Z)) \
82: + ((((dst) & TME_SPARC_IREG_MSBIT) != 0) \
83: * ((ccr_need) & TME_SPARC64_CCR_XCC_N)))
84:
85: /* this macro updates %icc and %xcc: */
86: #define TME_SPARC_RECODE_CCR_UPDATE(ic, ccr, ccr_need) \
87: do { \
88: if (TME_SPARC_VERSION((struct tme_sparc *) (ic)) >= 9) { \
89: ((struct tme_sparc *) (ic))->tme_sparc64_ireg_ccr \
90: = ((((struct tme_sparc *) (ic))->tme_sparc64_ireg_ccr \
91: & ~ccr_need) \
92: | ccr); \
93: } \
94: else { \
95: ((struct tme_sparc *) (ic))->tme_sparc32_ireg_psr \
96: = ((((struct tme_sparc *) (ic))->tme_sparc32_ireg_psr \
97: & ~TME_SPARC_ICC(ccr_need)) \
98: | TME_SPARC_ICC(ccr_need)); \
99: } \
100: } while (/* CONSTCOND */ 0)
101:
102: /* rename various things by the architecture size: */
103: #define _tme_sparc_flags_additive _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_additive)
104: #define _tme_sparc_flags_logical _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_logical)
105: #define _tme_sparc_flags_func_logical _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_func_logical)
106: #define _tme_sparc_flags_func_add _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_func_add)
107: #define _tme_sparc_flags_func_sub _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_func_sub)
108: #define _tme_sparc_recode_conds_func_icc _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_conds_func_icc)
109: #define _tme_sparc_recode_cc_init _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_cc_init)
110:
111: /* the sparc64 recode xcc conditions function: */
112: static int
113: _tme_sparc64_recode_conds_func_xcc(tme_recode_uguest_t flags, tme_uint32_t cond)
114: {
115: return (_tme_sparc_conds_icc
116: [TME_FIELD_MASK_EXTRACTU(flags, TME_SPARC64_CCR_XCC)]
117: & (1 << cond));
118: }
119:
120: #endif /* TME_SPARC_RECODE_SIZE(ic) == TME_RECODE_SIZE_32 */
121:
122: /* the additive instruction flags: */
123: static const struct tme_recode_flag _tme_sparc_flags_additive[] = {
124: #if TME_SPARC_VERSION(ic) >= 9
125: {
126: TME_RECODE_COND_N,
127: TME_RECODE_SIZE_64,
128: TME_SPARC64_CCR_XCC_N
129: },
130: {
131: TME_RECODE_COND_Z,
132: TME_RECODE_SIZE_64,
133: TME_SPARC64_CCR_XCC_Z
134: },
135: {
136: TME_RECODE_COND_V,
137: TME_RECODE_SIZE_64,
138: TME_SPARC64_CCR_XCC_V
139: },
140: {
141: TME_RECODE_COND_C,
142: TME_RECODE_SIZE_64,
143: TME_SPARC64_CCR_XCC_C
144: },
145: #endif /* TME_SPARC_VERSION(ic) >= 9 */
146: {
147: TME_RECODE_COND_N,
148: TME_RECODE_SIZE_32,
149: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_N)
150: },
151: {
152: TME_RECODE_COND_Z,
153: TME_RECODE_SIZE_32,
154: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_Z)
155: },
156: {
157: TME_RECODE_COND_V,
158: TME_RECODE_SIZE_32,
159: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_V)
160: },
161: {
162: TME_RECODE_COND_C,
163: TME_RECODE_SIZE_32,
164: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_C)
165: },
166: {
167: 0,
168: 0,
169: 0
170: }
171: };
172:
173: /* the logical instruction flags: */
174: static const struct tme_recode_flag _tme_sparc_flags_logical[] = {
175: #if TME_SPARC_VERSION(ic) >= 9
176: {
177: TME_RECODE_COND_N,
178: TME_RECODE_SIZE_64,
179: TME_SPARC64_CCR_XCC_N
180: },
181: {
182: TME_RECODE_COND_Z,
183: TME_RECODE_SIZE_64,
184: TME_SPARC64_CCR_XCC_Z
185: },
186: {
187: TME_RECODE_COND_FALSE,
188: 0,
189: TME_SPARC64_CCR_XCC_V
190: },
191: {
192: TME_RECODE_COND_FALSE,
193: 0,
194: TME_SPARC64_CCR_XCC_C
195: },
196: #endif /* TME_SPARC_VERSION(ic) >= 9 */
197: {
198: TME_RECODE_COND_N,
199: TME_RECODE_SIZE_32,
200: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_N)
201: },
202: {
203: TME_RECODE_COND_Z,
204: TME_RECODE_SIZE_32,
205: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_Z)
206: },
207: {
208: TME_RECODE_COND_FALSE,
209: 0,
210: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_V)
211: },
212: {
213: TME_RECODE_COND_FALSE,
214: 0,
215: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_C)
216: },
217: {
218: 0,
219: 0,
220: 0
221: }
222: };
223:
224: /* the logical instruction flags function: */
225: static void
226: _tme_sparc_flags_func_logical(struct tme_ic *ic,
227: tme_recode_uguest_t src1,
228: tme_recode_uguest_t src2,
229: tme_recode_uguest_t dst)
230: {
231: unsigned int ccr_need;
232:
233: ccr_need
234: = (TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_LOGICAL,
235: TME_SPARC_RECODE_SIZE(ic),
236: TME_RECODE_SIZE_32)
237: | TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_LOGICAL,
238: TME_SPARC_RECODE_SIZE(ic),
239: TME_SPARC_RECODE_SIZE(ic)));
240:
241: TME_SPARC_RECODE_CCR_UPDATE(ic,
242: TME_SPARC_RECODE_CCR_N_Z(dst, ccr_need),
243: ccr_need);
244: }
245:
246: /* the add instruction flags function: */
247: static void
248: _tme_sparc_flags_func_add(struct tme_ic *ic,
249: tme_recode_uguest_t src1,
250: tme_recode_uguest_t src2,
251: tme_recode_uguest_t dst)
252: {
253: unsigned int ccr_need;
254: unsigned int ccr;
255:
256: ccr_need
257: = (TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_ADDITIVE,
258: TME_SPARC_RECODE_SIZE(ic),
259: TME_RECODE_SIZE_32)
260: | TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_ADDITIVE,
261: TME_SPARC_RECODE_SIZE(ic),
262: TME_SPARC_RECODE_SIZE(ic)));
263:
264: /* make the %icc and %xcc N and Z flags: */
265: ccr = TME_SPARC_RECODE_CCR_N_Z(dst, ccr_need);
266:
267: /* if src1 and src2 both have bit 31 set, or if dst does not have
268: bit 31 set and either src1 or src2 does, set %icc.C: */
269: if (((tme_int32_t) ((src1 & src2) | (~dst & (src1 | src2)))) < 0) {
270: ccr += (ccr_need & TME_SPARC64_CCR_ICC_C);
271: }
272:
273: /* if src1 and src2 have the same bit 31, and dst has a different
274: bit 31, set %icc.V: */
275: if (((tme_int32_t) ((src2 ^ dst) & (src1 ^ ~src2))) < 0) {
276: ccr += (ccr_need & TME_SPARC64_CCR_ICC_V);
277: }
278:
279: /* if src1 and src2 both have the most-significant bit set, or if
280: dst does not have the most-significant bit set either src1 or
281: src2 does, set %xcc.C: */
282: if (((src1 & src2) | (~dst & (src1 | src2))) & TME_SPARC_IREG_MSBIT) {
283: ccr += (ccr_need & TME_SPARC64_CCR_XCC_C);
284: }
285:
286: /* if src1 and src2 have the same most-significant bit, and dst has
287: a different most-significant bit, set %xcc.V: */
288: if (((src2 ^ dst) & (src1 ^ ~src2)) & TME_SPARC_IREG_MSBIT) {
289: ccr += (ccr_need & TME_SPARC64_CCR_XCC_V);
290: }
291:
292: TME_SPARC_RECODE_CCR_UPDATE(ic, ccr, ccr_need);
293: }
294:
295: /* the sub instruction flags function: */
296: static void
297: _tme_sparc_flags_func_sub(struct tme_ic *ic,
298: tme_recode_uguest_t src1,
299: tme_recode_uguest_t src2,
300: tme_recode_uguest_t dst)
301: {
302: unsigned int ccr_need;
303: unsigned int ccr;
304:
305: ccr_need
306: = (TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_ADDITIVE,
307: TME_SPARC_RECODE_SIZE(ic),
308: TME_RECODE_SIZE_32)
309: | TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_ADDITIVE,
310: TME_SPARC_RECODE_SIZE(ic),
311: TME_SPARC_RECODE_SIZE(ic)));
312:
313: /* make the %icc and %xcc N and Z flags: */
314: ccr = TME_SPARC_RECODE_CCR_N_Z(dst, ccr_need);
315:
316: /* if src2 is greater than src1 in 32 bits, set %icc.C: */
317: if (((tme_uint32_t) src2) > ((tme_uint32_t) src1)) {
318: ccr += (ccr_need & TME_SPARC64_CCR_ICC_C);
319: }
320:
321: /* if src1 and src2 have different bit 31s, and dst has a different
322: bit 31 than src1, set %icc.V: */
323: if (((tme_int32_t) ((src1 ^ src2) & (src1 ^ dst))) < 0) {
324: ccr += (ccr_need & TME_SPARC64_CCR_ICC_V);
325: }
326:
327: /* if src2 is greater than src1, set %xcc.C: */
328: if (((tme_sparc_ireg_t) src2) > ((tme_sparc_ireg_t) src1)) {
329: ccr += (ccr_need & TME_SPARC64_CCR_XCC_C);
330: }
331:
332: /* if src1 and src2 have different most-significant bits, and dst
333: has a different most-significant bit than src1, set %xcc.V: */
334: if (((src1 ^ src2) & (src1 ^ dst)) & TME_SPARC_IREG_MSBIT) {
335: ccr += (ccr_need & TME_SPARC64_CCR_XCC_V);
336: }
337:
338: TME_SPARC_RECODE_CCR_UPDATE(ic, ccr, ccr_need);
339: }
340:
341: /* the sparc icc conditions function: */
342: static int
343: _tme_sparc_recode_conds_func_icc(tme_recode_uguest_t flags, tme_uint32_t cond)
344: {
345: return (_tme_sparc_conds_icc
346: [TME_FIELD_MASK_EXTRACTU(flags, TME_SPARC_ICC(TME_SPARC64_CCR_ICC))]
347: & (1 << cond));
348: }
349:
350: /* this initializes for condition codes: */
351: static void
352: _tme_sparc_recode_cc_init(struct tme_sparc *ic)
353: {
354: struct tme_recode_ic *recode_ic;
355: struct tme_recode_flags_group flags_group;
356: struct tme_recode_conds_group conds_group;
357:
358: /* recover the recode ic: */
359: recode_ic = ic->tme_sparc_recode_ic;
360:
361: /* make the common parts of a flags group: */
362: memset((char *) &flags_group, 0, sizeof(flags_group));
363: flags_group.tme_recode_flags_group_insn_size = TME_SPARC_RECODE_SIZE(ic);
364: if (TME_SPARC_VERSION(ic) <= 8) {
365: flags_group.tme_recode_flags_group_flags_reg_size = TME_RECODE_SIZE_32;
366: flags_group.tme_recode_flags_group_flags_reg = TME_SPARC32_IREG_PSR;
367: }
368: else {
369: flags_group.tme_recode_flags_group_flags_reg_size = TME_RECODE_SIZE_8;
370: flags_group.tme_recode_flags_group_flags_reg = TME_SPARC64_IREG_CCR << 3;
371: }
372:
373: /* make the flags thunk for addcc and addxcc: */
374: flags_group.tme_recode_flags_group_insn_class = TME_RECODE_INSN_CLASS_ADDITIVE;
375: flags_group.tme_recode_flags_group_flags = _tme_sparc_flags_additive;
376: flags_group.tme_recode_flags_group_guest_func = _tme_sparc_flags_func_add;
377: ic->tme_sparc_recode_flags_thunk_add
378: = tme_recode_flags_thunk(recode_ic,
379: &flags_group);
380:
381: /* make the flags thunk for subcc and subxcc: */
382: flags_group.tme_recode_flags_group_insn_class = TME_RECODE_INSN_CLASS_ADDITIVE;
383: flags_group.tme_recode_flags_group_flags = _tme_sparc_flags_additive;
384: flags_group.tme_recode_flags_group_guest_func = _tme_sparc_flags_func_sub;
385: ic->tme_sparc_recode_flags_thunk_sub
386: = tme_recode_flags_thunk(recode_ic,
387: &flags_group);
388:
389: /* make the flags thunk for the logical instructions: */
390: flags_group.tme_recode_flags_group_insn_class = TME_RECODE_INSN_CLASS_LOGICAL;
391: flags_group.tme_recode_flags_group_flags = _tme_sparc_flags_logical;
392: flags_group.tme_recode_flags_group_guest_func = _tme_sparc_flags_func_logical;
393: ic->tme_sparc_recode_flags_thunk_logical
394: = tme_recode_flags_thunk(recode_ic,
395: &flags_group);
396:
397: /* make the common parts of a conditions group: */
398: memset((char *) &conds_group, 0, sizeof(conds_group));
399: conds_group.tme_recode_conds_group_flags_reg_size = flags_group.tme_recode_flags_group_flags_reg_size;
400: conds_group.tme_recode_conds_group_flags_reg = flags_group.tme_recode_flags_group_flags_reg;
401: conds_group.tme_recode_conds_group_cond_count = TME_SPARC_COND_NOT;
402:
403: /* make the conditions thunk for %icc: */
404: conds_group.tme_recode_conds_group_flags = TME_SPARC_ICC(TME_SPARC64_CCR_ICC);
405: conds_group.tme_recode_conds_group_guest_func = _tme_sparc_recode_conds_func_icc;
406: ic->tme_sparc_recode_conds_thunk_icc
407: = tme_recode_conds_thunk(recode_ic,
408: &conds_group);
409:
410: /* if this is a sparc64: */
411: if (TME_SPARC_VERSION(ic) >= 9) {
412:
413: /* make the flags thunk for the sparc64 internal "rcc" flags.
414: this is identical to the flags thunk for the logical
415: instructions, except it uses the internal "rcc" register: */
416: flags_group.tme_recode_flags_group_flags_reg = TME_SPARC64_IREG_RCC << 3;
417: ic->tme_sparc_recode_flags_thunk_rcc
418: = tme_recode_flags_thunk(recode_ic,
419: &flags_group);
420:
421: /* make the conditions thunk for %xcc: */
422: conds_group.tme_recode_conds_group_flags = TME_SPARC64_CCR_XCC;
423: conds_group.tme_recode_conds_group_guest_func = _tme_sparc64_recode_conds_func_xcc;
424: ic->tme_sparc_recode_conds_thunk_xcc
425: = tme_recode_conds_thunk(recode_ic,
426: &conds_group);
427:
428: /* make the conditions thunk for the internal "rcc" flags. this
429: is identical to the conditions thunk for %xcc, except it uses
430: the internal "rcc" register: */
431: conds_group.tme_recode_conds_group_flags_reg = flags_group.tme_recode_flags_group_flags_reg;
432: ic->tme_sparc_recode_conds_thunk_rcc
433: = tme_recode_conds_thunk(recode_ic,
434: &conds_group);
435: }
436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.