|
|
1.1 root 1: /* Medium-level subroutines: convert bit-field store and extract
2: and shifts, multiplies and divides to rtl instructions.
3: Copyright (C) 1987, 1988 Free Software Foundation, Inc.
4:
5: This file is part of GNU CC.
6:
7: GNU CC is distributed in the hope that it will be useful,
8: but WITHOUT ANY WARRANTY. No author or distributor
9: accepts responsibility to anyone for the consequences of using it
10: or for whether it serves any particular purpose or works at all,
11: unless he says so in writing. Refer to the GNU CC General Public
12: License for full details.
13:
14: Everyone is granted permission to copy, modify and redistribute
15: GNU CC, but only under the conditions described in the
16: GNU CC General Public License. A copy of this license is
17: supposed to have been given to you along with GNU CC so you
18: can know your rights and responsibilities. It should be in a
19: file named COPYING. Among other things, the copyright notice
20: and this notice must be preserved on all copies. */
21:
22:
23: #include "config.h"
24: #include "rtl.h"
25: #include "tree.h"
26: #include "flags.h"
27: #include "insn-flags.h"
28: #include "insn-codes.h"
29: #include "insn-config.h"
30: #include "expr.h"
31: #include "recog.h"
32:
33: static rtx extract_split_bit_field ();
34: static rtx extract_fixed_bit_field ();
35: static void store_split_bit_field ();
36: static void store_fixed_bit_field ();
37:
38: /* Return an rtx representing minus the value of X. */
39:
40: rtx
41: negate_rtx (x)
42: rtx x;
43: {
44: if (GET_CODE (x) == CONST_INT)
45: return gen_rtx (CONST_INT, VOIDmode, - INTVAL (x));
46: else
47: return expand_unop (GET_MODE (x), neg_optab, x, 0, 0);
48: }
49:
50: /* Generate code to store value from rtx VALUE
51: into a bit-field within structure STR_RTX
52: containing BITSIZE bits starting at bit BITNUM.
53: FIELDMODE is the machine-mode of the FIELD_DECL node for this field. */
54:
55: /* ??? This should really have the ability to copy a word into a register
56: in order to store the bit-field into it, on machines whose insv insns
57: work that way. */
58:
59: rtx
60: store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value)
61: rtx str_rtx;
62: register int bitsize;
63: int bitnum;
64: enum machine_mode fieldmode;
65: rtx value;
66: {
67: int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
68: register int offset = bitnum / unit;
69: register int bitpos = bitnum % unit;
70: register rtx op0 = str_rtx;
71: rtx value1;
72:
73: if (GET_CODE (op0) == SUBREG)
74: {
75: offset += SUBREG_WORD (op0);
76: op0 = SUBREG_REG (op0);
77: }
78:
79: value = protect_from_queue (value, 0);
80:
81: if (flag_force_mem)
82: value = force_not_mem (value);
83:
84: if (GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD)
85: {
86: /* Storing in a full-word or multi-word field in a register
87: can be done with just SUBREG. */
88: if (GET_MODE (op0) != fieldmode)
89: op0 = gen_rtx (SUBREG, fieldmode, op0, offset);
90: emit_move_insn (op0, value);
91: return value;
92: }
93:
94: #ifdef BYTES_BIG_ENDIAN
95: /* If OP0 is a register, BITPOS must count within a word.
96: But as we have it, it counts within whatever size OP0 now has.
97: On a bigendian machine, these are not the same, so convert. */
98: if (GET_CODE (op0) != MEM && unit > GET_MODE_BITSIZE (GET_MODE (op0)))
99: bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
100: #endif
101:
102: /* Storing an lsb-aligned field in a register
103: can be done with a movestrict instruction. */
104:
105: if (GET_CODE (op0) != MEM
106: #ifdef BYTES_BIG_ENDIAN
107: && bitpos + bitsize == unit
108: #else
109: && bitpos == 0
110: #endif
111: && (GET_MODE (op0) == fieldmode
112: || (movstrict_optab->handlers[(int) fieldmode].insn_code
113: != CODE_FOR_nothing)))
114: {
115: /* Get appropriate low part of the value being stored. */
116: if (GET_CODE (value) == CONST_INT || GET_CODE (value) == REG)
117: value = gen_lowpart (fieldmode, value);
118: else if (!(GET_CODE (value) == SYMBOL_REF
119: || GET_CODE (value) == LABEL_REF
120: || GET_CODE (value) == CONST))
121: value = convert_to_mode (fieldmode, value, 0);
122:
123: if (GET_MODE (op0) == fieldmode)
124: emit_move_insn (op0, value);
125: else
126: emit_insn (GEN_FCN (movstrict_optab->handlers[(int) fieldmode].insn_code)
127: (gen_rtx (SUBREG, fieldmode, op0, offset), value));
128:
129: return value;
130: }
131:
132: /* From here on we can assume that the field to be stored in is an integer,
133: since it is shorter than a word. */
134:
135: /* OFFSET is the number of words or bytes (UNIT says which)
136: from STR_RTX to the first word or byte containing part of the field. */
137:
138: if (GET_CODE (op0) == REG)
139: {
140: if (offset != 0
141: || GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (SImode))
142: op0 = gen_rtx (SUBREG, SImode, op0, offset);
143: offset = 0;
144: }
145: else
146: {
147: op0 = protect_from_queue (op0, 1);
148: }
149:
150: /* Now OFFSET is nonzero only if OP0 is memory
151: and is therefore always measured in bytes. */
152:
153: #ifdef HAVE_insv
154: if (HAVE_insv
155: && !(bitsize == 1 && GET_CODE (value) == CONST_INT))
156: {
157: enum machine_mode mode0 = GET_MODE (op0);
158:
159: /* Add OFFSET into OP0's address. */
160: if (GET_CODE (op0) == MEM)
161: op0 = change_address (op0, QImode,
162: plus_constant (XEXP (op0, 0), offset));
163:
164: /* If op0 is a register, we need it in SImode
165: to make it acceptable to the format of insv. */
166: if (GET_CODE (op0) == SUBREG)
167: PUT_MODE (op0, SImode);
168: if (GET_CODE (op0) == REG && GET_MODE (op0) != SImode)
169: op0 = gen_rtx (SUBREG, SImode, op0, 0);
170:
171: /* Convert VALUE to SImode (which insv insn wants) in VALUE1. */
172: value1 = value;
173: if (GET_MODE (value) != SImode)
174: {
175: if (GET_MODE_BITSIZE (GET_MODE (value)) >= bitsize)
176: {
177: if (GET_CODE (value) != REG)
178: value1 = copy_to_reg (value);
179: /* Optimization: Don't bother really extending VALUE
180: if it has all the bits we will actually use. */
181: value1 = gen_rtx (SUBREG, SImode, value1, 0);
182: }
183: else if (!CONSTANT_P (value))
184: /* Parse phase is supposed to make VALUE's data type
185: match that of the component reference, which is a type
186: at least as wide as the field; so VALUE should have
187: a mode that corresponds to that type. */
188: abort ();
189: }
190:
191: /* If this machine's insv insists on a register,
192: get VALUE1 into a register. */
193: if (! (*insn_operand_predicate[(int) CODE_FOR_insv][3]) (value1, SImode))
194: value1 = force_reg (SImode, value1);
195:
196: /* On big-endian machines, we count bits from the most significant.
197: If the bit field insn does not, we must invert. */
198:
199: #if defined (BITS_BIG_ENDIAN) != defined (BYTES_BIG_ENDIAN)
200: bitpos = unit - 1 - bitpos;
201: #endif
202:
203: emit_insn (gen_insv (op0,
204: gen_rtx (CONST_INT, VOIDmode, bitsize),
205: gen_rtx (CONST_INT, VOIDmode, bitpos),
206: value1));
207: }
208: else
209: #endif
210: /* Insv is not available; store using shifts and boolean ops. */
211: store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
212: return value;
213: }
214:
215: /* Use shifts and boolean operations to store VALUE
216: into a bit field of width BITSIZE
217: in a memory location specified by OP0 except offset by OFFSET bytes.
218: The field starts at position BITPOS within the byte.
219: (If OP0 is a register, it may be SImode or a narrower mode,
220: but BITPOS still counts within a full word,
221: which is significant on bigendian machines.)
222:
223: Note that protect_from_queue has already been done on OP0 and VALUE. */
224:
225: static void
226: store_fixed_bit_field (op0, offset, bitsize, bitpos, value)
227: register rtx op0;
228: register int offset, bitsize, bitpos;
229: register rtx value;
230: {
231: register enum machine_mode mode;
232: int total_bits = BITS_PER_WORD;
233: rtx subtarget;
234: int all_zero = 0;
235: int all_one = 0;
236:
237: /* Add OFFSET to OP0's address (if it is in memory)
238: and if a single byte contains the whole bit field
239: change OP0 to a byte. */
240:
241: if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
242: {
243: /* Special treatment for a bit field split across two registers. */
244: if (bitsize + bitpos > BITS_PER_WORD)
245: {
246: store_split_bit_field (op0, bitsize, bitpos, value);
247: return;
248: }
249: }
250: else if (bitsize + bitpos <= BITS_PER_UNIT
251: && ! SLOW_BYTE_ACCESS)
252: {
253: total_bits = BITS_PER_UNIT;
254: op0 = change_address (op0, QImode,
255: plus_constant (XEXP (op0, 0), offset));
256: }
257: else
258: {
259: /* Get ref to word containing the field. */
260: /* Adjust BITPOS to be position within a word,
261: and OFFSET to be the offset of that word.
262: Then alter OP0 to refer to that word. */
263: bitpos += (offset % (BITS_PER_WORD / BITS_PER_UNIT)) * BITS_PER_UNIT;
264: offset -= (offset % (BITS_PER_WORD / BITS_PER_UNIT));
265: op0 = change_address (op0, SImode,
266: plus_constant (XEXP (op0, 0), offset));
267: /* Special treatment for a bit field split across two words. */
268: if (bitsize + bitpos > BITS_PER_WORD)
269: {
270: store_split_bit_field (op0, bitsize, bitpos, value);
271: return;
272: }
273: }
274:
275: mode = GET_MODE (op0);
276:
277: /* Now OP0 is either a byte or a word, and the bit field is contained
278: entirely within it. TOTAL_BITS and MODE say which one (byte or word).
279: BITPOS is the starting bit number within the byte or word.
280: (If OP0 is a word, it may actually have a mode narrower than SImode.) */
281:
282: #ifdef BYTES_BIG_ENDIAN
283: /* BITPOS is the distance between our msb
284: and that of the containing byte or word.
285: Convert it to the distance from the lsb. */
286:
287: bitpos = total_bits - bitsize - bitpos;
288: #endif
289: /* Now BITPOS is always the distance between our lsb
290: and that of the containing byte or word. */
291:
292: /* Shift VALUE left by BITPOS bits. If VALUE is not constant,
293: we must first convert its mode to MODE. */
294:
295: if (GET_CODE (value) == CONST_INT)
296: {
297: register int v = INTVAL (value);
298:
299: if (bitsize < HOST_BITS_PER_INT)
300: v &= (1 << bitsize) - 1;
301:
302: if (v == 0)
303: all_zero = 1;
304: else if (bitsize < HOST_BITS_PER_INT && v == (1 << bitsize) - 1)
305: all_one = 1;
306:
307: value = gen_rtx (CONST_INT, VOIDmode, v << bitpos);
308: }
309: else
310: {
311: int must_and = (GET_MODE_BITSIZE (GET_MODE (value)) != bitsize);
312:
313: if (GET_MODE (value) != mode)
314: {
315: if (GET_CODE (value) == REG && mode == QImode)
316: value = gen_rtx (SUBREG, mode, value, 0);
317: else
318: value = convert_to_mode (mode, value, 1);
319: }
320:
321: if (must_and && bitsize < HOST_BITS_PER_INT)
322: value = expand_bit_and (mode, value,
323: gen_rtx (CONST_INT, VOIDmode,
324: (1 << bitsize) - 1),
325: 0);
326: if (bitpos > 0)
327: value = expand_shift (LSHIFT_EXPR, mode, value,
328: build_int_2 (bitpos, 0), 0, 1);
329: }
330:
331: /* Now clear the chosen bits in OP0,
332: except that if VALUE is -1 we need not bother. */
333:
334: subtarget = op0;
335:
336: if (! all_one)
337: subtarget = expand_bit_and (mode, op0,
338: gen_rtx (CONST_INT, VOIDmode,
339: (~ (((1 << bitsize) - 1) << bitpos))
340: & ((1 << GET_MODE_BITSIZE (mode)) - 1)),
341: subtarget);
342:
343: /* Now logical-or VALUE into OP0, unless it is zero. */
344:
345: if (! all_zero)
346: subtarget = expand_binop (mode, ior_optab, subtarget, value,
347: op0, 1, OPTAB_LIB_WIDEN);
348: if (op0 != subtarget)
349: emit_move_insn (op0, subtarget);
350: }
351:
352: /* Store a bit field that is split across two words.
353:
354: OP0 is the REG, SUBREG or MEM rtx for the first of the two words.
355: BITSIZE is the field width; BITPOS the position of its first bit
356: (within the word).
357: VALUE is the value to store. */
358:
359: static void
360: store_split_bit_field (op0, bitsize, bitpos, value)
361: rtx op0;
362: int bitsize, bitpos;
363: rtx value;
364: {
365: /* BITSIZE_1 is size of the part in the first word. */
366: int bitsize_1 = BITS_PER_WORD - bitpos;
367: /* BITSIZE_2 is size of the rest (in the following word). */
368: int bitsize_2 = bitsize - bitsize_1;
369: rtx part1, part2;
370:
371: if (GET_MODE (value) != VOIDmode)
372: value = convert_to_mode (SImode, value, 1);
373: if (CONSTANT_P (value) && GET_CODE (value) != CONST_INT)
374: value = copy_to_reg (value);
375:
376: /* Split the value into two parts:
377: PART1 gets that which goes in the first word; PART2 the other. */
378: #ifdef BYTES_BIG_ENDIAN
379: /* PART1 gets the more significant part. */
380: if (GET_CODE (value) == CONST_INT)
381: {
382: part1 = gen_rtx (CONST_INT, VOIDmode,
383: (unsigned) (INTVAL (value)) >> bitsize_2);
384: part2 = gen_rtx (CONST_INT, VOIDmode,
385: (unsigned) (INTVAL (value)) & ((1 << bitsize_2) - 1));
386: }
387: else
388: {
389: part1 = extract_fixed_bit_field (SImode, value, 0, bitsize_1,
390: BITS_PER_WORD - bitsize, 0, 1);
391: part2 = extract_fixed_bit_field (SImode, value, 0, bitsize_2,
392: BITS_PER_WORD - bitsize_2, 0, 1);
393: }
394: #else
395: /* PART1 gets the less significant part. */
396: if (GET_CODE (value) == CONST_INT)
397: {
398: part1 = gen_rtx (CONST_INT, VOIDmode,
399: (unsigned) (INTVAL (value)) & ((1 << bitsize_1) - 1));
400: part2 = gen_rtx (CONST_INT, VOIDmode,
401: (unsigned) (INTVAL (value)) >> bitsize_1);
402: }
403: else
404: {
405: part1 = extract_fixed_bit_field (SImode, value, 0, bitsize_1, 0, 0, 1);
406: part2 = extract_fixed_bit_field (SImode, value, 0, bitsize_2,
407: bitsize_1, 0, 1);
408: }
409: #endif
410:
411: /* Store PART1 into the first word. */
412: store_fixed_bit_field (op0, 0, bitsize_1, bitpos, part1);
413:
414: /* Offset op0 to get to the following word. */
415: if (GET_CODE (op0) == MEM)
416: op0 = change_address (op0, SImode,
417: plus_constant (XEXP (op0, 0), UNITS_PER_WORD));
418: else if (GET_CODE (op0) == REG)
419: op0 = gen_rtx (SUBREG, SImode, op0, 1);
420: else
421: op0 = gen_rtx (SUBREG, SImode, SUBREG_REG (op0), SUBREG_WORD (op0) + 1);
422:
423: /* Store PART2 into the second word. */
424: store_fixed_bit_field (op0, 0, bitsize_2, 0, part2);
425: }
426:
427: /* Generate code to extract a byte-field from STR_RTX
428: containing BITSIZE bits, starting at BITNUM,
429: and put it in TARGET if possible (if TARGET is nonzero).
430: Regardless of TARGET, we return the rtx for where the value is placed.
431: It may be a QUEUED.
432:
433: STR_RTX is the structure containing the byte (a REG or MEM).
434: UNSIGNEDP is nonzero if this is an unsigned bit field.
435: MODE is the natural mode of the field value once extracted.
436: TMODE is the mode the caller would like the value to have;
437: but the value may be returned with type MODE instead.
438:
439: If a TARGET is specified and we can store in it at no extra cost,
440: we do so, and return TARGET.
441: Otherwise, we return a REG of mode TMODE or MODE, with TMODE preferred
442: if they are equally easy. */
443:
444: rtx
445: extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, target, mode, tmode)
446: rtx str_rtx;
447: register int bitsize;
448: int bitnum;
449: int unsignedp;
450: rtx target;
451: enum machine_mode mode, tmode;
452: {
453: int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
454: register int offset = bitnum / unit;
455: register int bitpos = bitnum % unit;
456: register rtx op0 = str_rtx;
457: rtx spec_target = target;
458: rtx bitsize_rtx, bitpos_rtx;
459: rtx spec_target_subreg = 0;
460:
461: if (tmode == VOIDmode)
462: tmode = mode;
463:
464: while (GET_CODE (op0) == SUBREG)
465: {
466: offset += SUBREG_WORD (op0);
467: op0 = SUBREG_REG (op0);
468: }
469:
470: #ifdef BYTES_BIG_ENDIAN
471: /* If OP0 is a register, BITPOS must count within a word.
472: But as we have it, it counts within whatever size OP0 now has.
473: On a bigendian machine, these are not the same, so convert. */
474: if (GET_CODE (op0) != MEM && unit > GET_MODE_BITSIZE (GET_MODE (op0)))
475: bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
476: #endif
477:
478: /* Extracting a full-word or multi-word value
479: from a structure in a register.
480: This can be done with just SUBREG.
481: So too extracting a subword value in
482: the least significant part of the register. */
483:
484: if (GET_CODE (op0) == REG
485: && (bitsize >= BITS_PER_WORD
486: || ((bitsize == GET_MODE_BITSIZE (mode)
487: || bitsize == GET_MODE_BITSIZE (QImode)
488: || bitsize == GET_MODE_BITSIZE (HImode))
489: #ifdef BYTES_BIG_ENDIAN
490: && bitpos + bitsize == BITS_PER_WORD
491: #else
492: && bitpos == 0
493: #endif
494: )))
495: {
496: enum machine_mode mode1 = mode;
497:
498: if (bitsize == GET_MODE_BITSIZE (QImode))
499: mode1 = QImode;
500: if (bitsize == GET_MODE_BITSIZE (HImode))
501: mode1 = HImode;
502:
503: if (mode1 != GET_MODE (op0))
504: op0 = gen_rtx (SUBREG, mode1, op0, offset);
505:
506: if (mode1 != mode)
507: return convert_to_mode (tmode, op0, unsignedp);
508: return op0;
509: }
510:
511: /* From here on we know the desired field is smaller than a word
512: so we can assume it is an integer. So we can safely extract it as one
513: size of integer, if necessary, and then truncate or extend
514: to the size that is wanted. */
515:
516: /* OFFSET is the number of words or bytes (UNIT says which)
517: from STR_RTX to the first word or byte containing part of the field. */
518:
519: if (GET_CODE (op0) == REG)
520: {
521: if (offset != 0
522: || GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (SImode))
523: op0 = gen_rtx (SUBREG, SImode, op0, offset);
524: offset = 0;
525: }
526: else
527: {
528: op0 = protect_from_queue (str_rtx, 1);
529: }
530:
531: /* Now OFFSET is nonzero only for memory operands. */
532:
533: if (unsignedp)
534: {
535: #ifdef HAVE_extzv
536: if (HAVE_extzv)
537: {
538: /* Get ref to first byte containing part of the field. */
539: if (GET_CODE (op0) == MEM)
540: op0 = change_address (op0, QImode,
541: plus_constant (XEXP (op0, 0), offset));
542:
543: /* If op0 is a register, we need it in SImode
544: to make it acceptable to the format of extv. */
545: if (GET_CODE (op0) == SUBREG)
546: PUT_MODE (op0, SImode);
547: if (GET_CODE (op0) == REG && GET_MODE (op0) != SImode)
548: op0 = gen_rtx (SUBREG, SImode, op0, 0);
549:
550: if (target == 0
551: || (flag_force_mem && GET_CODE (target) == MEM))
552: target = spec_target = gen_reg_rtx (tmode);
553:
554: if (GET_MODE (target) != SImode)
555: {
556: if (GET_CODE (target) == REG)
557: spec_target_subreg = target = gen_rtx (SUBREG, SImode, target, 0);
558: else
559: target = gen_reg_rtx (SImode);
560: }
561:
562: /* If this machine's extzv insists on a register target,
563: make sure we have one. */
564: if (! (*insn_operand_predicate[(int) CODE_FOR_extzv][0]) (target, SImode))
565: target = gen_reg_rtx (SImode);
566:
567: /* On big-endian machines, we count bits from the most significant.
568: If the bit field insn does not, we must invert. */
569: #if defined (BITS_BIG_ENDIAN) != defined (BYTES_BIG_ENDIAN)
570: bitpos = unit - 1 - bitpos;
571: #endif
572:
573: bitsize_rtx = gen_rtx (CONST_INT, VOIDmode, bitsize);
574: bitpos_rtx = gen_rtx (CONST_INT, VOIDmode, bitpos);
575:
576: emit_insn (gen_extzv (protect_from_queue (target, 1),
577: op0, bitsize_rtx, bitpos_rtx));
578: }
579: else
580: #endif
581: target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
582: target, 1);
583: }
584: else
585: {
586: #ifdef HAVE_extv
587: if (HAVE_extv)
588: {
589: /* Get ref to first byte containing part of the field. */
590: if (GET_CODE (op0) == MEM)
591: op0 = change_address (op0, QImode,
592: plus_constant (XEXP (op0, 0), offset));
593:
594: /* If op0 is a register, we need it in QImode
595: to make it acceptable to the format of extv. */
596: if (GET_CODE (op0) == SUBREG)
597: PUT_MODE (op0, SImode);
598: if (GET_CODE (op0) == REG && GET_MODE (op0) != SImode)
599: op0 = gen_rtx (SUBREG, SImode, op0, 0);
600:
601: if (target == 0
602: || (flag_force_mem && GET_CODE (target) == MEM))
603: target = spec_target = gen_reg_rtx (tmode);
604:
605: if (GET_MODE (target) != SImode)
606: {
607: if (GET_CODE (target) == REG)
608: spec_target_subreg = target = gen_rtx (SUBREG, SImode, target, 0);
609: else
610: target = gen_reg_rtx (SImode);
611: }
612:
613: /* If this machine's extv insists on a register target,
614: make sure we have one. */
615: if (! (*insn_operand_predicate[(int) CODE_FOR_extzv][0]) (target, SImode))
616: target = gen_reg_rtx (SImode);
617:
618: /* On big-endian machines, we count bits from the most significant.
619: If the bit field insn does not, we must invert. */
620: #if defined (BITS_BIG_ENDIAN) != defined (BYTES_BIG_ENDIAN)
621: bitpos = unit - 1 - bitpos;
622: #endif
623:
624: bitsize_rtx = gen_rtx (CONST_INT, VOIDmode, bitsize);
625: bitpos_rtx = gen_rtx (CONST_INT, VOIDmode, bitpos);
626:
627: emit_insn (gen_extv (protect_from_queue (target, 1), op0,
628: bitsize_rtx, bitpos_rtx));
629: }
630: else
631: #endif
632: target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
633: target, 0);
634: }
635: if (target == spec_target)
636: return target;
637: if (target == spec_target_subreg)
638: return spec_target;
639: if (GET_MODE (target) != tmode && GET_MODE (target) != mode)
640: return convert_to_mode (tmode, target, unsignedp);
641: return target;
642: }
643:
644: /* Extract a bit field using shifts and boolean operations
645: Returns an rtx to represent the value.
646: OP0 addresses a register (word) or memory (byte).
647: BITPOS says which bit within the word or byte the bit field starts in.
648: OFFSET says how many bytes farther the bit field starts;
649: it is 0 if OP0 is a register.
650: BITSIZE says how many bits long the bit field is.
651: (If OP0 is a register, it may be narrower than SImode,
652: but BITPOS still counts within a full word,
653: which is significant on bigendian machines.)
654:
655: UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value).
656: If TARGET is nonzero, attempts to store the value there
657: and return TARGET, but this is not guaranteed.
658: If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */
659:
660: static rtx
661: extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, target, unsignedp)
662: enum machine_mode tmode;
663: register rtx op0, target;
664: register int offset, bitsize, bitpos;
665: int unsignedp;
666: {
667: int total_bits = BITS_PER_WORD;
668: enum machine_mode mode;
669: rtx orig = op0;
670:
671: if (GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
672: {
673: /* Special treatment for a bit field split across two registers. */
674: if (bitsize + bitpos > BITS_PER_WORD)
675: return extract_split_bit_field (op0, bitsize, bitpos, unsignedp);
676: }
677: else if (bitsize + bitpos <= BITS_PER_UNIT && ! SLOW_BYTE_ACCESS)
678: {
679: /* If the bit field fits entirely in one byte of memory,
680: let OP0 be that byte. We must add OFFSET to its address. */
681: total_bits = BITS_PER_UNIT;
682: op0 = change_address (op0, QImode,
683: plus_constant (XEXP (op0, 0), offset));
684: }
685: else
686: {
687: #ifdef STRICT_ALIGNMENT
688: #ifndef STRUCTURE_SIZE_BOUNDARY
689: /* The following code assumes that OP0 is aligned
690: such that a word can be fetched there.
691: This could be because words don't need to be aligned,
692: or because all structures are suitably aligned. */
693: abort ();
694: #endif
695: #endif
696:
697: /* Get ref to word containing the field. */
698: /* Adjust BITPOS to be position within a word,
699: and OFFSET to be the offset of that word. */
700: bitpos += (offset % (BITS_PER_WORD / BITS_PER_UNIT)) * BITS_PER_UNIT;
701: offset -= (offset % (BITS_PER_WORD / BITS_PER_UNIT));
702: op0 = change_address (op0, SImode,
703: plus_constant (XEXP (op0, 0), offset));
704:
705: /* Special treatment for a bit field split across two words. */
706: if (bitsize + bitpos > BITS_PER_WORD)
707: return extract_split_bit_field (op0, bitsize, bitpos, unsignedp);
708: }
709:
710: mode = GET_MODE (op0);
711:
712: #ifdef BYTES_BIG_ENDIAN
713: /* BITPOS is the distance between our msb
714: and that of the containing byte or word.
715: Convert it to the distance from the lsb. */
716:
717: bitpos = total_bits - bitsize - bitpos;
718: #endif
719: /* Now BITPOS is always the distance between our lsb
720: and that of the containing byte or word.
721: We have reduced the big-endian case to the little-endian case. */
722:
723: if (unsignedp)
724: {
725: if (bitpos)
726: {
727: /* If the field does not already start at the lsb,
728: shift it so it does. */
729: tree amount = build_int_2 (bitpos, 0);
730: /* Maybe propagate the target for the shift. */
731: /* Certainly do so if we will return the value of the shift. */
732: rtx subtarget = (target != 0 && GET_CODE (target) == REG
733: && FUNCTION_VALUE_REGNO_P (REGNO (target))
734: ? target : 0);
735: if (tmode != mode) subtarget = 0;
736: op0 = expand_shift (RSHIFT_EXPR, mode, op0, amount, subtarget, 1);
737: }
738: /* Convert the value to the desired mode. */
739: if (mode != tmode)
740: op0 = convert_to_mode (tmode, op0, 1);
741:
742: /* Unless the msb of the field used to be the msb when we shifted,
743: mask out the upper bits. */
744:
745: if ((GET_MODE_BITSIZE (mode) != bitpos + bitsize
746: #if 0
747: #ifdef SLOW_ZERO_EXTEND
748: /* Always generate an `and' if
749: we just zero-extended op0 and SLOW_ZERO_EXTEND, since it
750: will combine fruitfully with the zero-extend. */
751: || tmode != mode
752: #endif
753: #endif
754: )
755: && bitsize < HOST_BITS_PER_INT)
756: return expand_bit_and (GET_MODE (op0), op0,
757: gen_rtx (CONST_INT, VOIDmode, (1 << bitsize) - 1),
758: target);
759: return op0;
760: }
761:
762: /* To extract a signed bit-field, first shift its msb to the msb of the word,
763: then arithmetic-shift its lsb to the lsb of the word. */
764: op0 = force_reg (mode, op0);
765: if (mode != tmode)
766: target = 0;
767: if (GET_MODE_BITSIZE (QImode) < GET_MODE_BITSIZE (mode)
768: && GET_MODE_BITSIZE (QImode) >= bitsize + bitpos)
769: mode = QImode, op0 = convert_to_mode (QImode, op0, 0);
770: if (GET_MODE_BITSIZE (HImode) < GET_MODE_BITSIZE (mode)
771: && GET_MODE_BITSIZE (HImode) >= bitsize + bitpos)
772: mode = HImode, op0 = convert_to_mode (HImode, op0, 0);
773: if (GET_MODE_BITSIZE (mode) != (bitsize + bitpos))
774: {
775: tree amount = build_int_2 (GET_MODE_BITSIZE (mode) - (bitsize + bitpos), 0);
776: /* Maybe propagate the target for the shift. */
777: /* Certainly do so if we will return the value of the shift. */
778: rtx subtarget = (target != 0 && GET_CODE (target) == REG
779: && FUNCTION_VALUE_REGNO_P (REGNO (target))
780: ? target : 0);
781: op0 = expand_shift (LSHIFT_EXPR, mode, op0, amount, subtarget, 1);
782: }
783:
784: return expand_shift (RSHIFT_EXPR, mode, op0,
785: build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0),
786: target, 0);
787: }
788:
789: /* Extract a bit field that is split across two words
790: and return an RTX for the result.
791:
792: OP0 is the REG, SUBREG or MEM rtx for the first of the two words.
793: BITSIZE is the field width; BITPOS, position of its first bit, in the word.
794: UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend. */
795:
796: static rtx
797: extract_split_bit_field (op0, bitsize, bitpos, unsignedp)
798: rtx op0;
799: int bitsize, bitpos, unsignedp;
800: {
801: /* BITSIZE_1 is size of the part in the first word. */
802: int bitsize_1 = BITS_PER_WORD - bitpos;
803: /* BITSIZE_2 is size of the rest (in the following word). */
804: int bitsize_2 = bitsize - bitsize_1;
805: rtx part1, part2, result;
806:
807: /* Get the part of the bit field from the first word. */
808: part1 = extract_fixed_bit_field (SImode, op0, 0, bitsize_1, bitpos, 0, 1);
809:
810: /* Offset op0 by 1 word to get to the following one. */
811: if (GET_CODE (op0) == MEM)
812: op0 = change_address (op0, SImode,
813: plus_constant (XEXP (op0, 0), UNITS_PER_WORD));
814: else if (GET_CODE (op0) == REG)
815: op0 = gen_rtx (SUBREG, SImode, op0, 1);
816: else
817: op0 = gen_rtx (SUBREG, SImode, SUBREG_REG (op0), SUBREG_WORD (op0) + 1);
818:
819: /* Get the part of the bit field from the second word. */
820: part2 = extract_fixed_bit_field (SImode, op0, 0, bitsize_2, 0, 0, 1);
821:
822: /* Shift the more significant part up to fit above the other part. */
823: #ifdef BYTES_BIG_ENDIAN
824: part1 = expand_shift (LSHIFT_EXPR, SImode, part1,
825: build_int_2 (bitsize_2, 0), 0, 1);
826: #else
827: part2 = expand_shift (LSHIFT_EXPR, SImode, part2,
828: build_int_2 (bitsize_1, 0), 0, 1);
829: #endif
830:
831: /* Combine the two parts with bitwise or. This works
832: because we extracted both parts as unsigned bit fields. */
833: result = expand_binop (SImode, ior_optab, part1, part2, 0, 1,
834: OPTAB_LIB_WIDEN);
835:
836: /* Unsigned bit field: we are done. */
837: if (unsignedp)
838: return result;
839: /* Signed bit field: sign-extend with two arithmetic shifts. */
840: result = expand_shift (LSHIFT_EXPR, SImode, result,
841: build_int_2 (BITS_PER_WORD - bitsize, 0), 0, 0);
842: return expand_shift (RSHIFT_EXPR, SImode, result,
843: build_int_2 (BITS_PER_WORD - bitsize, 0), 0, 0);
844: }
845:
846: /* Add INC into TARGET. */
847:
848: void
849: expand_inc (target, inc)
850: rtx target, inc;
851: {
852: rtx value = expand_binop (GET_MODE (target), add_optab,
853: target, inc,
854: target, 0, OPTAB_LIB_WIDEN);
855: if (value != target)
856: emit_move_insn (target, value);
857: }
858:
859: /* Subtract INC from TARGET. */
860:
861: void
862: expand_dec (target, dec)
863: rtx target, dec;
864: {
865: rtx value = expand_binop (GET_MODE (target), sub_optab,
866: target, dec,
867: target, 0, OPTAB_LIB_WIDEN);
868: if (value != target)
869: emit_move_insn (target, value);
870: }
871:
872: /* Output a shift instruction for expression code CODE,
873: with SHIFTED being the rtx for the value to shift,
874: and AMOUNT the tree for the amount to shift by.
875: Store the result in the rtx TARGET, if that is convenient.
876: If UNSIGNEDP is nonzero, do a logical shift; otherwise, arithmetic.
877: Return the rtx for where the value is. */
878:
879: /* Pastel, for shifts, converts shift count to SImode here
880: independent of the mode being shifted.
881: Should that be done in an earlier pass?
882: It turns out not to matter for C. */
883:
884: rtx
885: expand_shift (code, mode, shifted, amount, target, unsignedp)
886: enum tree_code code;
887: register enum machine_mode mode;
888: rtx shifted;
889: tree amount;
890: register rtx target;
891: int unsignedp;
892: {
893: register rtx op1, temp = 0;
894: register int left = (code == LSHIFT_EXPR || code == LROTATE_EXPR);
895: int try;
896: rtx negated = 0;
897: int rotate = code == LROTATE_EXPR || code == RROTATE_EXPR;
898:
899: /* Previously detected shift-counts computed by NEGATE_EXPR
900: and shifted in the other direction; but that does not work
901: on all machines. */
902:
903: op1 = expand_expr (amount, 0, VOIDmode, 0);
904:
905: for (try = 0; temp == 0 && try < 3; try++)
906: {
907: enum optab_methods methods;
908: if (try == 0)
909: methods = OPTAB_DIRECT;
910: else if (try == 1)
911: methods = OPTAB_WIDEN;
912: else
913: methods = OPTAB_LIB_WIDEN;
914:
915: if (rotate)
916: {
917: /* Widening does not work for rotation. */
918: if (methods != OPTAB_DIRECT)
919: methods = OPTAB_LIB;
920:
921: temp = expand_binop (mode,
922: left ? rotl_optab : rotr_optab,
923: shifted, op1, target, -1, methods);
924: /* If there is no shift instruction for the desired direction,
925: try negating the shift count and shifting in the other direction.
926: If a machine has only a left shift instruction then we are
927: entitled to assume it shifts right with negative args. */
928: if (temp == 0)
929: {
930: if (negated != 0)
931: ;
932: else if (GET_CODE (op1) == CONST_INT)
933: negated = gen_rtx (CONST_INT, VOIDmode, -INTVAL (op1));
934: else
935: negated = expand_unop (mode, neg_optab, op1, 0, 0);
936: temp = expand_binop (mode,
937: left ? rotr_optab : rotl_optab,
938: shifted, negated, target, -1, methods);
939: }
940: }
941: else if (unsignedp)
942: {
943: temp = expand_binop (mode,
944: left ? lshl_optab : lshr_optab,
945: shifted, op1, target, unsignedp, methods);
946: if (temp == 0 && left)
947: temp = expand_binop (mode, ashl_optab,
948: shifted, op1, target, unsignedp, methods);
949: if (temp == 0)
950: {
951: if (negated != 0)
952: ;
953: else if (GET_CODE (op1) == CONST_INT)
954: negated = gen_rtx (CONST_INT, VOIDmode, -INTVAL (op1));
955: else
956: negated = expand_unop (mode, neg_optab, op1, 0, 0);
957: temp = expand_binop (mode,
958: left ? lshr_optab : lshl_optab,
959: shifted, negated,
960: target, unsignedp, methods);
961: }
962:
963: if (temp != 0)
964: return temp;
965: }
966: /* Do arithmetic shifts.
967: Also, if we are going to widen the operand, we can just as well
968: use an arithmetic right-shift instead of a logical one. */
969: if (! rotate && (! unsignedp || (! left && methods == OPTAB_WIDEN)))
970: {
971: /* Arithmetic shift */
972:
973: temp = expand_binop (mode,
974: left ? ashl_optab : ashr_optab,
975: shifted, op1, target, unsignedp, methods);
976: if (temp == 0)
977: {
978: if (negated != 0)
979: ;
980: else if (GET_CODE (op1) == CONST_INT)
981: negated = gen_rtx (CONST_INT, VOIDmode, -INTVAL (op1));
982: else
983: negated = expand_unop (mode, neg_optab, op1, 0, 0);
984: temp = expand_binop (mode,
985: left ? ashr_optab : ashl_optab,
986: shifted, negated, target, unsignedp, methods);
987: }
988: if (temp != 0)
989: return temp;
990: }
991:
992: if (unsignedp)
993: {
994: /* No logical shift insn in either direction =>
995: try a bit-field extract instruction if we have one. */
996: #ifdef HAVE_extzv
997: #ifndef BITS_BIG_ENDIAN
998: if (HAVE_extzv && !left
999: && ((methods == OPTAB_DIRECT && mode == SImode)
1000: || (methods == OPTAB_WIDEN
1001: && GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))))
1002: {
1003: rtx shifted1 = convert_to_mode (SImode, shifted, 1);
1004: rtx target1 = target;
1005:
1006: /* If -fforce-mem, don't let the operand be in memory. */
1007: if (flag_force_mem && GET_CODE (shifted1) == MEM)
1008: shifted1 = force_not_mem (shifted1);
1009:
1010: /* If this machine's extzv insists on a register for
1011: operand 1, arrange for that. */
1012: if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][1])
1013: (shifted1, SImode)))
1014: shifted1 = force_reg (SImode, shifted1);
1015:
1016: /* If we don't have or cannot use a suggested target,
1017: make a place for the result, in the proper mode. */
1018: if (methods == OPTAB_WIDEN || target1 == 0
1019: || ! ((*insn_operand_predicate[(int) CODE_FOR_extzv][0])
1020: (target1, SImode)))
1021: target1 = gen_reg_rtx (SImode);
1022:
1023: /* If this machine's extzv insists on a register for
1024: operand 3, arrange for that. */
1025: if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][3])
1026: (op1, SImode)))
1027: op1 = force_reg (SImode, op1);
1028:
1029: op1 = protect_from_queue (op1, 1);
1030:
1031: /* TEMP gets the width of the bit field to extract:
1032: wordsize minus # bits to shift by. */
1033: if (GET_CODE (op1) == CONST_INT)
1034: temp = gen_rtx (CONST_INT, VOIDmode,
1035: (GET_MODE_BITSIZE (mode) - INTVAL (op1)));
1036: else
1037: temp = expand_binop (SImode, sub_optab,
1038: gen_rtx (CONST_INT, VOIDmode,
1039: GET_MODE_BITSIZE (mode)),
1040: op1, gen_reg_rtx (SImode),
1041: 0, OPTAB_LIB_WIDEN);
1042: /* Now extract with width TEMP, omitting OP1 least sig bits. */
1043: emit_insn (gen_extzv (protect_from_queue (target1, 1),
1044: protect_from_queue (shifted1, 0),
1045: temp, op1));
1046: return convert_to_mode (mode, target1, 1);
1047: }
1048: /* Can also do logical shift with signed bit-field extract
1049: followed by inserting the bit-field at a different position.
1050: That strategy is not yet implemented. */
1051: #endif /* not BITS_BIG_ENDIAN */
1052: #endif /* HAVE_extzv */
1053: /* We have failed to generate the logical shift and will abort. */
1054: }
1055: }
1056: if (temp == 0)
1057: abort ();
1058: return temp;
1059: }
1060:
1061: /* Output an instruction or two to bitwise-and OP0 with OP1
1062: in mode MODE, with output to TARGET if convenient and TARGET is not zero.
1063: Returns where the result is. */
1064:
1065: rtx
1066: expand_bit_and (mode, op0, op1, target)
1067: enum machine_mode mode;
1068: rtx op0, op1, target;
1069: {
1070: register rtx temp;
1071:
1072: /* First try to open-code it directly. */
1073: temp = expand_binop (mode, and_optab, op0, op1, target, 1, OPTAB_DIRECT);
1074: if (temp == 0)
1075: {
1076: rtx compl;
1077: /* If that fails, try to open code using a clear-bits insn. */
1078: if (GET_CODE (op1) == CONST_INT
1079: && GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT)
1080: compl = gen_rtx (CONST_INT, VOIDmode,
1081: ((1 << GET_MODE_BITSIZE (mode)) - 1) & ~INTVAL (op1));
1082: else
1083: compl = expand_unop (mode, one_cmpl_optab, op1, 0, 1);
1084: temp = expand_binop (mode, andcb_optab, op0, compl, target,
1085: 1, OPTAB_DIRECT);
1086: }
1087: if (temp == 0)
1088: /* If still no luck, try library call or wider modes. */
1089: temp = expand_binop (mode, and_optab, op0, op1, target,
1090: 1, OPTAB_LIB_WIDEN);
1091:
1092: if (temp == 0)
1093: abort ();
1094: return temp;
1095: }
1096:
1097: /* Perform a multiplication and return an rtx for the result.
1098: MODE is mode of value; OP0 and OP1 are what to multiply (rtx's);
1099: TARGET is a suggestion for where to store the result (an rtx).
1100:
1101: We check specially for a constant integer as OP1.
1102: If you want this check for OP0 as well, then before calling
1103: you should swap the two operands if OP0 would be constant. */
1104:
1105: rtx
1106: expand_mult (mode, op0, op1, target, unsignedp)
1107: enum machine_mode mode;
1108: register rtx op0, op1, target;
1109: int unsignedp;
1110: {
1111: /* Don't use the function value register as a target
1112: since we have to read it as well as write it,
1113: and function-inlining gets confused by this. */
1114: if (target && REG_P (target) && FUNCTION_VALUE_REGNO_P (REGNO (target)))
1115: target = 0;
1116:
1117: if (GET_CODE (op1) == CONST_INT)
1118: {
1119: register int foo;
1120: int bar;
1121: int negate = INTVAL (op1) < 0;
1122: int absval = INTVAL (op1) * (negate ? -1 : 1);
1123:
1124: /* Is multiplier a power of 2, or minus that? */
1125: foo = exact_log2 (absval);
1126: if (foo >= 0)
1127: {
1128: rtx tem = expand_shift (LSHIFT_EXPR, mode, op0,
1129: build_int_2 (foo, 0),
1130: target, 0);
1131: return negate ? negate_rtx (tem) : tem;
1132: }
1133: /* Is multiplier a sum of two powers of 2, or minus that? */
1134: bar = floor_log2 (absval);
1135: foo = exact_log2 (absval - (1 << bar));
1136: if (bar >= 0 && foo >= 0)
1137: {
1138: rtx pow1 = ((foo == 0) ? op0
1139: : expand_shift (LSHIFT_EXPR, mode, op0,
1140: build_int_2 (foo, 0),
1141: 0, 0));
1142: rtx pow2 = expand_shift (LSHIFT_EXPR, mode, op0,
1143: build_int_2 (bar, 0),
1144: 0, 0);
1145: rtx tem = force_operand (gen_rtx (PLUS, mode, pow1, pow2), target);
1146: return negate ? negate_rtx (tem) : tem;
1147: }
1148: }
1149: /* This used to use umul_optab if unsigned,
1150: but I think that for non-widening multiply there is no difference
1151: between signed and unsigned. */
1152: op0 = expand_binop (mode, smul_optab,
1153: op0, op1, target, unsignedp, OPTAB_LIB_WIDEN);
1154: if (op0 == 0)
1155: abort ();
1156: return op0;
1157: }
1158:
1159: /* Emit the code to divide OP0 by OP1, putting the result in TARGET
1160: if that is convenient, and returning where the result is.
1161: You may request either the quotient or the remainder as the result;
1162: specify REM_FLAG nonzero to get the remainder.
1163:
1164: CODE is the expression code for which kind of division this is;
1165: it controls how rounding is done. MODE is the machine mode to use.
1166: UNSIGNEDP nonzero means do unsigned division. */
1167:
1168: /* ??? For CEIL_MOD_EXPR, can compute incorrect remainder with ANDI
1169: and then correct it by or'ing in missing high bits
1170: if result of ANDI is nonzero.
1171: For ROUND_MOD_EXPR, can use ANDI and then sign-extend the result.
1172: This could optimize to a bfexts instruction.
1173: But C doesn't use these operations, so their optimizations are
1174: left for later. */
1175:
1176: rtx
1177: expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
1178: int rem_flag;
1179: enum tree_code code;
1180: enum machine_mode mode;
1181: register rtx op0, op1, target;
1182: int unsignedp;
1183: {
1184: register rtx label;
1185: register rtx temp;
1186: int log = -1;
1187: int can_clobber_op0;
1188: int mod_insn_no_good = 0;
1189: rtx adjusted_op0 = op0;
1190:
1191: /* Don't use the function value register as a target
1192: since we have to read it as well as write it,
1193: and function-inlining gets confused by this. */
1194: if (target && REG_P (target) && FUNCTION_VALUE_REGNO_P (REGNO (target)))
1195: target = 0;
1196:
1197: if (target == 0)
1198: {
1199: target = gen_reg_rtx (mode);
1200: }
1201:
1202: /* Don't clobber an operand while doing a multi-step calculation. */
1203: if ((rem_flag && rtx_equal_p (target, op0))
1204: || rtx_equal_p (target, op1))
1205: target = gen_reg_rtx (mode);
1206:
1207: can_clobber_op0 = (GET_CODE (op0) == REG && op0 == target);
1208:
1209: if (GET_CODE (op1) == CONST_INT)
1210: log = exact_log2 (INTVAL (op1));
1211:
1212: /* If log is >= 0, we are dividing by 2**log, and will do it by shifting,
1213: which is really floor-division. Otherwise we will really do a divide,
1214: and we assume that is trunc-division.
1215:
1216: We must correct the dividend by adding or subtracting something
1217: based on the divisor, in order to do the kind of rounding specified
1218: by CODE. The correction depends on what kind of rounding is actually
1219: available, and that depends on whether we will shift or divide. */
1220:
1221: switch (code)
1222: {
1223: case TRUNC_MOD_EXPR:
1224: case TRUNC_DIV_EXPR:
1225: if (log >= 0 && ! unsignedp)
1226: {
1227: label = gen_label_rtx ();
1228: if (! can_clobber_op0)
1229: adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target);
1230: emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0);
1231: emit_jump_insn (gen_bge (label));
1232: expand_inc (adjusted_op0, plus_constant (op1, -1));
1233: emit_label (label);
1234: mod_insn_no_good = 1;
1235: }
1236: break;
1237:
1238: case FLOOR_DIV_EXPR:
1239: case FLOOR_MOD_EXPR:
1240: if (log < 0 && ! unsignedp)
1241: {
1242: label = gen_label_rtx ();
1243: if (! can_clobber_op0)
1244: adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target);
1245: emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0);
1246: emit_jump_insn (gen_bge (label));
1247: expand_dec (adjusted_op0, op1);
1248: expand_inc (adjusted_op0, const1_rtx);
1249: emit_label (label);
1250: mod_insn_no_good = 1;
1251: }
1252: break;
1253:
1254: case CEIL_DIV_EXPR:
1255: case CEIL_MOD_EXPR:
1256: if (! can_clobber_op0)
1257: adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target);
1258: if (log < 0)
1259: {
1260: if (! unsignedp)
1261: {
1262: label = gen_label_rtx ();
1263: emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0);
1264: emit_jump_insn (gen_ble (label));
1265: }
1266: expand_inc (adjusted_op0, op1);
1267: expand_dec (adjusted_op0, const1_rtx);
1268: if (! unsignedp)
1269: emit_label (label);
1270: }
1271: else
1272: {
1273: adjusted_op0 = expand_binop (GET_MODE (target), add_optab,
1274: adjusted_op0, plus_constant (op1, -1),
1275: 0, 0, OPTAB_LIB_WIDEN);
1276: }
1277: mod_insn_no_good = 1;
1278: break;
1279:
1280: case ROUND_DIV_EXPR:
1281: case ROUND_MOD_EXPR:
1282: if (! can_clobber_op0)
1283: adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target);
1284: if (log < 0)
1285: {
1286: op1 = expand_shift (RSHIFT_EXPR, mode, op1, integer_one_node, 0, 0);
1287: if (! unsignedp)
1288: {
1289: label = gen_label_rtx ();
1290: emit_cmp_insn (adjusted_op0, const0_rtx, 0, 0);
1291: emit_jump_insn (gen_bge (label));
1292: expand_unop (mode, neg_optab, op1, op1, 0);
1293: emit_label (label);
1294: }
1295: expand_inc (adjusted_op0, op1);
1296: }
1297: else
1298: {
1299: op1 = gen_rtx (CONST_INT, VOIDmode, INTVAL (op1) / 2);
1300: expand_inc (adjusted_op0, op1);
1301: }
1302: mod_insn_no_good = 1;
1303: break;
1304: }
1305:
1306: if (rem_flag && !mod_insn_no_good)
1307: {
1308: /* Try to produce the remainder directly */
1309: if (log >= 0)
1310: {
1311: return expand_bit_and (mode, adjusted_op0,
1312: gen_rtx (CONST_INT, VOIDmode,
1313: INTVAL (op1) - 1),
1314: target);
1315: }
1316: else
1317: {
1318: /* See if we can do remainder without a library call. */
1319: temp = expand_binop (mode,
1320: unsignedp ? umod_optab : smod_optab,
1321: adjusted_op0, op1, target,
1322: unsignedp, OPTAB_WIDEN);
1323: if (temp != 0)
1324: return temp;
1325: /* No luck there.
1326: Can we do remainder and divide at once without a library call? */
1327: temp = gen_reg_rtx (mode);
1328: if (expand_twoval_binop (unsignedp ? udivmod_optab : sdivmod_optab,
1329: adjusted_op0, op1,
1330: 0, temp, unsignedp))
1331: return temp;
1332: temp = 0;
1333: }
1334: }
1335:
1336: /* Produce the quotient. */
1337: if (log >= 0)
1338: temp = expand_shift (RSHIFT_EXPR, mode, adjusted_op0,
1339: build_int_2 (exact_log2 (INTVAL (op1)), 0),
1340: target, unsignedp);
1341: else if (rem_flag && !mod_insn_no_good)
1342: /* If producing quotient in order to subtract for remainder,
1343: and a remainder subroutine would be ok,
1344: don't use a divide subroutine. */
1345: temp = expand_binop (mode, unsignedp ? udiv_optab : sdiv_optab,
1346: adjusted_op0, op1, target,
1347: unsignedp, OPTAB_WIDEN);
1348: else
1349: temp = expand_binop (mode, unsignedp ? udiv_optab : sdiv_optab,
1350: adjusted_op0, op1, target,
1351: unsignedp, OPTAB_LIB_WIDEN);
1352:
1353: /* If we really want the remainder, get it by subtraction. */
1354: if (rem_flag)
1355: {
1356: if (temp == 0)
1357: {
1358: /* No divide instruction either. Use library for remainder. */
1359: temp = expand_binop (mode,
1360: unsignedp ? umod_optab : smod_optab,
1361: op0, op1, target,
1362: unsignedp, OPTAB_LIB_WIDEN);
1363: }
1364: else
1365: {
1366: /* We divided. Now finish doing X - Y * (X / Y). */
1367: temp = expand_mult (mode, temp, op1, temp, unsignedp);
1368: if (! temp) abort ();
1369: temp = expand_binop (mode, sub_optab, op0,
1370: temp, target, unsignedp, OPTAB_LIB_WIDEN);
1371: }
1372: }
1373:
1374: if (temp == 0)
1375: abort ();
1376: return temp;
1377: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.