/* True if the current function is an interrupt handler
(either via #pragma or an attribute specification). */
-int interrupt_handler;
+static int interrupt_handler;
/* True if the current function is an OS Task
(via an attribute specification). */
-int os_task;
+static int os_task;
/* True if the current function is a monitor
(via an attribute specification). */
-int monitor;
+static int monitor;
/* True if a #pragma saveall has been seen for the current function. */
-int pragma_saveall;
+static int pragma_saveall;
static const char *const names_big[] =
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" };
/* Various operations needed by the following, indexed by CPU_TYPE. */
-static const char *const h8_push_ops[2] = { "push", "push.l" };
-static const char *const h8_pop_ops[2] = { "pop", "pop.l" };
-static const char *const h8_mov_ops[2] = { "mov.w", "mov.l" };
-
const char *h8_push_op, *h8_pop_op, *h8_mov_op;
\f
/* Initialize the GCC target structure. */
void
h8300_init_once ()
{
+ static const char *const h8_push_ops[2] = { "push" , "push.l" };
+ static const char *const h8_pop_ops[2] = { "pop" , "pop.l" };
+ static const char *const h8_mov_ops[2] = { "mov.w", "mov.l" };
+
if (TARGET_H8300)
{
cpu_type = (int) CPU_H8300;
rtx x;
int b;
{
- static const char *const names_small[] =
- {"r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
- "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7l", "r7h"};
+ static const char *const names_small[] = {
+ "r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
+ "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7l", "r7h"
+ };
return names_small[REGNO (x) * 2 + b];
}
/* REGNO must be saved/restored across calls if this macro is true. */
-#define WORD_REG_USED(regno) \
- (regno < 7 \
- /* No need to save registers if this function will not return. */\
- && ! TREE_THIS_VOLATILE (current_function_decl) \
- && (pragma_saveall \
- /* Save any call saved register that was used. */ \
- || (regs_ever_live[regno] && !call_used_regs[regno]) \
- /* Save the frame pointer if it was used. */ \
- || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno])\
- /* Save any register used in an interrupt handler. */ \
- || (interrupt_handler && regs_ever_live[regno]) \
- /* Save call clobbered registers in non-leaf interrupt \
- handlers. */ \
- || (interrupt_handler \
- && call_used_regs[regno] \
+#define WORD_REG_USED(regno) \
+ (regno < 7 \
+ /* No need to save registers if this function will not return. */ \
+ && ! TREE_THIS_VOLATILE (current_function_decl) \
+ && (pragma_saveall \
+ /* Save any call saved register that was used. */ \
+ || (regs_ever_live[regno] && !call_used_regs[regno]) \
+ /* Save the frame pointer if it was used. */ \
+ || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno]) \
+ /* Save any register used in an interrupt handler. */ \
+ || (interrupt_handler && regs_ever_live[regno]) \
+ /* Save call clobbered registers in non-leaf interrupt \
+ handlers. */ \
+ || (interrupt_handler \
+ && call_used_regs[regno] \
&& !current_function_is_leaf)))
/* Output assembly language to FILE for the operation OP with operand size
}
else
{
- /* A constant addition/subtraction takes 2 states in
- QImode. It takes 6 states in HImode, requiring the
- constant to be loaded to a register first, and a lot more
- in SImode. Thus the only case we can win is when either
- HImode or SImode is used. */
- if (mode != QImode
+ /* We do not profit directly by splitting addition or
+ subtraction of 3 and 4. However, since these are
+ implemented as a sequence of adds or subs, they do not
+ clobber (cc0) unlike a sequence of add.b and add.x. */
+ if (mode == HImode
&& (value == 2 + 1
|| value == 2 + 2))
return 1;
pragma_saveall = 1;
}
-/* If the next arg with MODE and TYPE is to be passed in a register, return
- the rtx to represent where it is passed. CUM represents the state after
- the last argument. NAMED is not used. */
-
-static const char *const hand_list[] =
-{
- "__main",
- "__cmpsi2",
- "__divhi3",
- "__modhi3",
- "__udivhi3",
- "__umodhi3",
- "__divsi3",
- "__modsi3",
- "__udivsi3",
- "__umodsi3",
- "__mulhi3",
- "__mulsi3",
- "__reg_memcpy",
- "__reg_memset",
- "__ucmpsi2",
- 0,
-};
-
-/* Return an RTX to represent where a value with mode MODE will be returned
- from a function. If the result is 0, the argument is pushed. */
+/* If the next function argument with MODE and TYPE is to be passed in
+ a register, return a reg RTX for the hard register in which to pass
+ the argument. CUM represents the state after the last argument.
+ If the argument is to be pushed, NULL_RTX is returned. */
rtx
function_arg (cum, mode, type, named)
tree type;
int named;
{
- rtx result = 0;
+ static const char *const hand_list[] = {
+ "__main",
+ "__cmpsi2",
+ "__divhi3",
+ "__modhi3",
+ "__udivhi3",
+ "__umodhi3",
+ "__divsi3",
+ "__modsi3",
+ "__udivsi3",
+ "__umodsi3",
+ "__mulhi3",
+ "__mulsi3",
+ "__reg_memcpy",
+ "__reg_memset",
+ "__ucmpsi2",
+ 0,
+ };
+
+ rtx result = NULL_RTX;
const char *fname;
int regpass = 0;
/* Never pass unnamed arguments in registers. */
if (!named)
- return 0;
+ return NULL_RTX;
/* Pass 3 regs worth of data in regs when user asked on the command line. */
if (TARGET_QUICKCALL)
regpass = 3;
/* If calling hand written assembler, use 4 regs of args. */
-
if (cum->libcall)
{
const char * const *p;
fname = XSTR (cum->libcall, 0);
/* See if this libcall is one of the hand coded ones. */
-
for (p = hand_list; *p && strcmp (*p, fname) != 0; p++)
;
else
size = GET_MODE_SIZE (mode);
- if (size + cum->nbytes > regpass * UNITS_PER_WORD)
- {
- result = 0;
- }
- else
- {
- switch (cum->nbytes / UNITS_PER_WORD)
- {
- case 0:
- result = gen_rtx_REG (mode, 0);
- break;
- case 1:
- result = gen_rtx_REG (mode, 1);
- break;
- case 2:
- result = gen_rtx_REG (mode, 2);
- break;
- case 3:
- result = gen_rtx_REG (mode, 3);
- break;
- default:
- result = 0;
- }
- }
+ if (size + cum->nbytes <= regpass * UNITS_PER_WORD
+ && cum->nbytes / UNITS_PER_WORD <= 3)
+ result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
}
return result;
\f
/* Documentation for the machine specific operand escapes:
- 'A' print rn in H8/300 mode, erN in H8/300H mode
- 'C' print (operand - 2).
'E' like s but negative.
'F' like t but negative.
'G' constant just the negative
- 'M' turn a 'M' constant into its negative mod 2.
- 'P' if operand is incing/decing sp, print .w, otherwise .b.
'R' print operand as a byte:8 address if appropriate, else fall back to
'X' handling.
'S' print operand as a long word
'T' print operand as a word
- 'U' if operand is incing/decing sp, print l, otherwise nothing.
'V' find the set bit, and print its number.
'W' find the clear bit, and print its number.
'X' print operand as a byte
If this operand isn't a register, fall back to 'R' handling.
'Z' print int & 7.
'b' print the bit opcode
- 'c' print the ibit opcode
- 'd' bcc if EQ, bcs if NE
'e' first word of 32 bit value - if reg, then least reg. if mem
then least. if const then most sig word
'f' second word of 32 bit value - if reg, then biggest reg. if mem
then +2. if const then least sig word
- 'g' bcs if EQ, bcc if NE
'j' print operand as condition code.
'k' print operand as reverse condition code.
's' print as low byte of 16 bit value
rtx x;
int code;
{
- /* This is used for communication between the 'P' and 'U' codes. */
- static const char *last_p;
-
/* This is used for communication between codes V,W,Z and Y. */
static int bitint;
switch (code)
{
- case 'A':
- if (GET_CODE (x) == REG)
- fprintf (file, "%s", h8_reg_names[REGNO (x)]);
- else
- goto def;
- break;
- case 'C':
- fprintf (file, "#%d", INTVAL (x) - 2);
- break;
case 'E':
switch (GET_CODE (x))
{
abort ();
fprintf (file, "#%d", 0xff & (-INTVAL (x)));
break;
- case 'M':
- /* For 3/-3 and 4/-4, the other 2 is handled separately. */
- switch (INTVAL (x))
- {
- case 2:
- case 4:
- case -2:
- case -4:
- fprintf (file, "#2");
- break;
- case 1:
- case 3:
- case -1:
- case -3:
- fprintf (file, "#1");
- break;
- default:
- abort ();
- }
- break;
- case 'P':
- if (REGNO (XEXP (XEXP (x, 0), 0)) == STACK_POINTER_REGNUM)
- {
- last_p = "";
- fprintf (file, ".w");
- }
- else
- {
- last_p = "l";
- fprintf (file, ".b");
- }
- break;
case 'S':
if (GET_CODE (x) == REG)
fprintf (file, "%s", names_extended[REGNO (x)]);
else
goto def;
break;
- case 'U':
- fprintf (file, "%s%s", names_big[REGNO (x)], last_p);
- break;
case 'V':
bitint = exact_log2 (INTVAL (x));
if (bitint == -1)
break;
}
break;
- case 'c':
- switch (GET_CODE (x))
- {
- case IOR:
- fprintf (file, "bior");
- break;
- case XOR:
- fprintf (file, "bixor");
- break;
- case AND:
- fprintf (file, "biand");
- break;
- default:
- break;
- }
- break;
- case 'd':
- switch (GET_CODE (x))
- {
- case EQ:
- fprintf (file, "bcc");
- break;
- case NE:
- fprintf (file, "bcs");
- break;
- default:
- abort ();
- }
- break;
case 'e':
switch (GET_CODE (x))
{
abort ();
}
break;
- case 'g':
- switch (GET_CODE (x))
- {
- case NE:
- fprintf (file, "bcc");
- break;
- case EQ:
- fprintf (file, "bcs");
- break;
- default:
- abort ();
- }
- break;
case 'j':
asm_fprintf (file, cond_string (GET_CODE (x)));
break;
1) the special insn (in case of AND or XOR),
2) the word-wise insn, and
3) The byte-wise insn. */
- if ((TARGET_H8300H || TARGET_H8300S)
- && ((det & 0x0000ffff) == 0x0000ffff)
- && code != IOR)
+ if ((det & 0x0000ffff) == 0x0000ffff
+ && (TARGET_H8300 ? (code == AND) : (code != IOR)))
output_asm_insn ((code == AND)
? "sub.w\t%f0,%f0" : "not.w\t%f0",
operands);
}
}
- if ((TARGET_H8300H || TARGET_H8300S)
- && ((det & 0xffff0000) == 0xffff0000)
- && code != IOR)
+ if ((det & 0xffff0000) == 0xffff0000
+ && (TARGET_H8300 ? (code == AND) : (code != IOR)))
output_asm_insn ((code == AND)
? "sub.w\t%e0,%e0" : "not.w\t%e0",
operands);
\f
/* Shifts.
- We devote a fair bit of code to getting efficient shifts since we can only
- shift one bit at a time on the H8/300 and H8/300H and only one or two
- bits at a time on the H8/S.
-
- The basic shift methods:
+ We devote a fair bit of code to getting efficient shifts since we
+ can only shift one bit at a time on the H8/300 and H8/300H and only
+ one or two bits at a time on the H8/S.
- * loop shifts -- emit a loop using one (or two on H8/S) bit shifts;
- this is the default. SHIFT_LOOP
+ All shift code falls into one of the following ways of
+ implementation:
- * inlined shifts -- emit straight line code for the shift; this is
- used when a straight line shift is about the same size or smaller
- than a loop. We allow the inline version to be slightly longer in
- some cases as it saves a register. SHIFT_INLINE
+ o SHIFT_INLINE: Emit straight line code for the shift; this is used
+ when a straight line shift is about the same size or smaller than
+ a loop.
- * rotate + and -- rotate the value the opposite direction, then
- mask off the values we don't need. This is used when only a few
- of the bits in the original value will survive in the shifted value.
- Again, this is used when it's about the same size or smaller than
- a loop. We allow this version to be slightly longer as it is usually
- much faster than a loop. SHIFT_ROT_AND
+ o SHIFT_ROT_AND: Rotate the value the opposite direction, then mask
+ off the bits we don't need. This is used when only a few of the
+ bits in the original value will survive in the shifted value.
- * swap (+ shifts) -- often it's possible to swap bytes/words to
- simulate a shift by 8/16. Once swapped a few inline shifts can be
- added if the shift count is slightly more than 8 or 16. This is used
- when it's about the same size or smaller than a loop. We allow this
- version to be slightly longer as it is usually much faster than a loop.
- SHIFT_SPECIAL
+ o SHIFT_SPECIAL: Often it's possible to move a byte or a word to
+ simulate a shift by 8, 16, or 24 bits. Once moved, a few inline
+ shifts can be added if the shift count is slightly more than 8 or
+ 16. This case also includes other oddballs that are not worth
+ explaning here.
- * There other oddballs. Not worth explaining. SHIFT_SPECIAL
+ o SHIFT_LOOP: Emit a loop using one (or two on H8/S) bit shifts.
- Here are some thoughts on what the absolutely positively best code is.
- "Best" here means some rational trade-off between code size and speed,
- where speed is more preferred but not at the expense of generating 20 insns.
+ Here are some thoughts on what the absolutely positively best code
+ is. "Best" here means some rational trade-off between code size
+ and speed, where speed is more preferred but not at the expense of
+ generating 20 insns.
- A trailing '*' after the shift count indicates the "best" mode isn't
- implemented.
+ Below, a trailing '*' after the shift count indicates the "best"
+ mode isn't implemented. We only describe SHIFT_SPECIAL cases to
+ simplify the table. For other cases, refer to shift_alg_[qhs]i.
H8/300 QImode shifts
- 1-4 - do them inline
- 5-6 - ASHIFT | LSHIFTRT: rotate, mask off other bits
- ASHIFTRT: loop
- 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits
- ASHIFTRT: shll, subx (propagate carry bit to all bits)
+ 7 - ASHIFTRT: shll, subx (propagate carry bit to all bits)
H8/300 HImode shifts
- 1-4 - do them inline
- 5-6 - loop
7 - shift 2nd half other way into carry.
copy 1st half into 2nd half
rotate 2nd half other way with carry
sign extend 1st half (ASHIFTRT)
8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT)
9-12 - do shift by 8, inline remaining shifts
- 13-14* - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0
- - ASHIFTRT: loop
- 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0
- - ASHIFTRT: shll, subx, set other byte
+ 15 - ASHIFTRT: shll, subx, set other byte
H8/300 SImode shifts
- 1-2 - do them inline
- 3-6 - loop
7* - shift other way once, move bytes into place,
move carry into place (possibly with sign extension)
8 - move bytes into place, zero or sign extend other
- 9-14 - loop
15* - shift other way once, move word into place, move carry into place
16 - move word, zero or sign extend other
- 17-23 - loop
24* - move bytes into place, zero or sign extend other
- 25-27 - loop
- 28-30* - ASHIFT | LSHIFTRT: rotate top byte, mask, move byte into place,
- zero others
- ASHIFTRT: loop
- 31 - ASHIFT | LSHIFTRT: rotate top byte, mask, move byte into place,
- zero others
- ASHIFTRT: shll top byte, subx, copy to other bytes
+ 31 - ASHIFTRT: shll top byte, subx, copy to other bytes
H8/300H QImode shifts (same as H8/300 QImode shifts)
- 1-4 - do them inline
- 5-6 - ASHIFT | LSHIFTRT: rotate, mask off other bits
- ASHIFTRT: loop
- 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits
- ASHIFTRT: shll, subx (propagate carry bit to all bits)
+ 7 - ASHIFTRT: shll, subx (propagate carry bit to all bits)
H8/300H HImode shifts
- 1-4 - do them inline
- 5-6 - loop
7 - shift 2nd half other way into carry.
copy 1st half into 2nd half
rotate entire word other way using carry
sign extend remaining bits (ASHIFTRT)
8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT)
9-12 - do shift by 8, inline remaining shifts
- 13-14 - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0
- - ASHIFTRT: loop
- 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0
- - ASHIFTRT: shll, subx, set other byte
+ 15 - ASHIFTRT: shll, subx, set other byte
H8/300H SImode shifts
(These are complicated by the fact that we don't have byte level access to
the top word.)
A word is: bytes 3,2,1,0 (msb -> lsb), word 1,0 (msw -> lsw)
- 1-4 - do them inline
- 5-14 - loop
15* - shift other way once, move word into place, move carry into place
(with sign extension for ASHIFTRT)
16 - move word into place, zero or sign extend other
17-20 - do 16bit shift, then inline remaining shifts
- 20-23 - loop
24* - ASHIFT: move byte 0(msb) to byte 1, zero byte 0,
move word 0 to word 1, zero word 0
LSHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
sign extend byte 0, sign extend word 0
25-27* - either loop, or
do 24 bit shift, inline rest
- 28-30 - ASHIFT: rotate 4/3/2, mask
- LSHIFTRT: rotate 4/3/2, mask
- ASHIFTRT: loop
31 - shll, subx byte 0, sign extend byte 0, sign extend word 0
H8/S QImode shifts
- 1-6 - do them inline
- 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits
- ASHIFTRT: shll, subx (propagate carry bit to all bits)
+ 7 - ASHIFTRT: shll, subx (propagate carry bit to all bits)
H8/S HImode shifts
- 1-7 - do them inline
8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT)
9-12 - do shift by 8, inline remaining shifts
- 13-14 - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0
- - ASHIFTRT: loop
- 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0
- - ASHIFTRT: shll, subx, set other byte
+ 15 - ASHIFTRT: shll, subx, set other byte
H8/S SImode shifts
(These are complicated by the fact that we don't have byte level access to
the top word.)
A word is: bytes 3,2,1,0 (msb -> lsb), word 1,0 (msw -> lsw)
- 1-10 - do them inline
- 11-14 - loop
15* - shift other way once, move word into place, move carry into place
(with sign extension for ASHIFTRT)
16 - move word into place, zero or sign extend other
17-20 - do 16bit shift, then inline remaining shifts
- 21-23 - loop
24* - ASHIFT: move byte 0(msb) to byte 1, zero byte 0,
move word 0 to word 1, zero word 0
LSHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
sign extend byte 0, sign extend word 0
25-27* - either loop, or
do 24 bit shift, inline rest
- 28-30 - ASHIFT: rotate 4/3/2, mask
- LSHIFTRT: rotate 4/3/2, mask
- ASHIFTRT: loop
31 - shll, subx byte 0, sign extend byte 0, sign extend word 0
Panic!!! */
return 1;
}
-/* Shift algorithm determination.
-
- There are various ways of doing a shift:
- SHIFT_INLINE: If the amount is small enough, just generate as many one-bit
- shifts as we need.
- SHIFT_ROT_AND: If the amount is large but close to either end, rotate the
- necessary bits into position and then set the rest to zero.
- SHIFT_SPECIAL: Hand crafted assembler.
- SHIFT_LOOP: If the above methods fail, just loop. */
+/* See above for explanation of this enum. */
enum shift_alg
{
/* Emit the assembler code for doing shifts. */
const char *
-emit_a_shift (insn, operands)
- rtx insn ATTRIBUTE_UNUSED;
+output_a_shift (operands)
rtx *operands;
{
static int loopend_lab;
n = info.remainder;
/* Emit two bit shifts first. */
- while (n > 1 && info.shift2 != NULL)
+ if (info.shift2 != NULL)
{
- output_asm_insn (info.shift2, operands);
- n -= 2;
+ for (; n > 1; n -= 2)
+ output_asm_insn (info.shift2, operands);
}
/* Now emit one bit shifts for any residual. */
- while (n > 0)
- {
- output_asm_insn (info.shift1, operands);
- n -= 1;
- }
+ for (; n > 0; n--)
+ output_asm_insn (info.shift1, operands);
/* Keep track of CC. */
if (info.cc_valid_p)
{
int m = GET_MODE_BITSIZE (mode) - n;
int mask = (shift_type == SHIFT_ASHIFT
- ? ((1 << (GET_MODE_BITSIZE (mode) - n)) - 1) << n
- : (1 << (GET_MODE_BITSIZE (mode) - n)) - 1);
+ ? ((1 << m) - 1) << n
+ : (1 << m) - 1);
char insn_buf[200];
/* Not all possibilities of rotate are supported. They shouldn't
abort ();
/* Emit two bit rotates first. */
- while (m > 1 && info.shift2 != NULL)
+ if (info.shift2 != NULL)
{
- output_asm_insn (info.shift2, operands);
- m -= 2;
+ for (; m > 1; m -= 2)
+ output_asm_insn (info.shift2, operands);
}
/* Now single bit rotates for any residual. */
- while (m > 0)
- {
- output_asm_insn (info.shift1, operands);
- m -= 1;
- }
+ for (; m > 0; m--)
+ output_asm_insn (info.shift1, operands);
/* Now mask off the high bits. */
if (TARGET_H8300)
sprintf (insn_buf, "and\t#%d,%%s0\n\tand\t#%d,%%t0",
mask & 255, mask >> 8);
break;
- case SImode:
- abort ();
default:
- break;
+ abort ();
}
}
else
int
expand_a_rotate (code, operands)
- int code;
+ enum rtx_code code;
rtx operands[];
{
rtx dst = operands[0];
const char *
emit_a_rotate (code, operands)
- int code;
+ enum rtx_code code;
rtx *operands;
{
rtx dst = operands[0];
}
const char *
-output_simode_bld (bild, log2, operands)
+output_simode_bld (bild, operands)
int bild;
- int log2;
rtx operands[];
{
/* Clear the destination register. */
else
output_asm_insn ("sub.w\t%e0,%e0\n\tsub.w\t%f0,%f0", operands);
- /* Get the bit number we want to load. */
- if (log2)
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
-
/* Now output the bit load or bit inverse load, and store it in
the destination. */
if (bild)
rtx insn;
int length ATTRIBUTE_UNUSED;
{
- rtx pat;
+ rtx pat = PATTERN (insn);
/* We must filter these out before calling get_attr_adjust_length. */
- if (GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER
- || GET_CODE (PATTERN (insn)) == SEQUENCE
- || GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ if (GET_CODE (pat) == USE
+ || GET_CODE (pat) == CLOBBER
+ || GET_CODE (pat) == SEQUENCE
+ || GET_CODE (pat) == ADDR_VEC
+ || GET_CODE (pat) == ADDR_DIFF_VEC)
return 0;
if (get_attr_adjust_length (insn) == ADJUST_LENGTH_NO)
return 0;
- pat = PATTERN (insn);
-
/* Adjust length for reg->mem and mem->reg copies. */
if (GET_CODE (pat) == SET
&& (GET_CODE (SET_SRC (pat)) == MEM
shift = INTVAL (XEXP (src, 1));
/* According to ANSI, negative shift is undefined. It is
considered to be zero in this case (see function
- emit_a_shift above). */
+ output_a_shift above). */
if (shift < 0)
shift = 0;