m32r.h (UPPER16_P): Fix calculation.
* m32r/m32r.h (UPPER16_P): Fix calculation. * m32r/m32r.c (two_insn_const_operand): New function. (m32r_print_operand): Handle 'X'. * m32r/m32r.md (movsi): Tweak. (*movsi_insn): Output hex value of constants too. (movsi define_split): Add. (andsi3,orsi3,xorsi3): Output hex value of constants too. From-SVN: r13857
This commit is contained in:
parent
4e007b6eea
commit
4d6c607f2e
@ -707,6 +707,22 @@ reg_or_cmp_int16_operand (op, mode)
|
||||
return CMP_INT16_P (INTVAL (op));
|
||||
}
|
||||
|
||||
/* Return true if OP is a const_int requiring two instructions to load. */
|
||||
|
||||
int
|
||||
two_insn_const_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
if (GET_CODE (op) != CONST_INT)
|
||||
return 0;
|
||||
if (INT16_P (INTVAL (op))
|
||||
|| UINT24_P (INTVAL (op))
|
||||
|| UPPER16_P (INTVAL (op)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return true if OP is an acceptable argument for a single word
|
||||
move source. */
|
||||
|
||||
@ -1667,6 +1683,18 @@ m32r_print_operand (file, x, code)
|
||||
output_operand_lossage ("invalid operand to %N code");
|
||||
return;
|
||||
|
||||
case 'X' :
|
||||
/* Print a const_int in hex. Used in comments. */
|
||||
if (GET_CODE (x) == CONST_INT)
|
||||
fprintf (file,
|
||||
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
|
||||
"0x%x",
|
||||
#else
|
||||
"0x%lx",
|
||||
#endif
|
||||
INTVAL (x));
|
||||
return;
|
||||
|
||||
case '#' :
|
||||
fputs (IMMEDIATE_PREFIX, file);
|
||||
return;
|
||||
|
@ -593,7 +593,7 @@ extern enum reg_class m32r_regno_reg_class[];
|
||||
#define INT16_P(X) ((unsigned) ((X) + 0x8000) < 0x10000)
|
||||
#define CMP_INT16_P(X) ((unsigned) ((X) - 1 + 0x8000) < 0x10000)
|
||||
#define UINT16_P(X) ((unsigned) (X) < 0x10000)
|
||||
#define UPPER16_P(X) (((X) & 0xffff0000) == 0)
|
||||
#define UPPER16_P(X) (((X) & ~0xffff0000) == 0)
|
||||
#define UINT24_P(X) ((unsigned) (X) < 0x1000000)
|
||||
#define INT32_P(X) ((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
|
||||
&& (X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
|
||||
|
@ -168,19 +168,21 @@
|
||||
""
|
||||
"
|
||||
{
|
||||
/* Everything except mem = const or mem = mem can be done easily.
|
||||
If medium or large code model, symbols have to be loaded with seth/add3.
|
||||
Objects in the small data area are handled too. */
|
||||
/* Everything except mem = const or mem = mem can be done easily. */
|
||||
|
||||
if (GET_CODE (operands[0]) == MEM)
|
||||
operands[1] = force_reg (SImode, operands[1]);
|
||||
|
||||
/* Small Data Area reference? */
|
||||
if (small_data_operand (operands[1], SImode))
|
||||
{
|
||||
emit_insn (gen_movsi_sda (operands[0], operands[1]));
|
||||
DONE;
|
||||
}
|
||||
else if (addr32_operand (operands[1], SImode))
|
||||
|
||||
/* If medium or large code model, symbols have to be loaded with
|
||||
seth/add3. */
|
||||
if (addr32_operand (operands[1], SImode))
|
||||
{
|
||||
emit_insn (gen_movsi_addr32 (operands[0], operands[1]));
|
||||
DONE;
|
||||
@ -194,15 +196,61 @@
|
||||
"register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
|
||||
"@
|
||||
mv %0,%1
|
||||
ldi %0,%#%1
|
||||
ldi %0,%#%1
|
||||
ld24 %0,%#%1
|
||||
ldi %0,%#%1 ; %X1
|
||||
ldi %0,%#%1 ; %X1
|
||||
ld24 %0,%#%1 ; %X1
|
||||
seth %0,%#%T1
|
||||
seth %0,%#%T1\;or3 %0,%0,%#%B1
|
||||
ld %0,%1
|
||||
st %1,%0"
|
||||
[(set_attr "type" "move,move,move4,move4,move4,multi,load,store")])
|
||||
|
||||
; Try to use a four byte / two byte pair for constants not loadable with
|
||||
; ldi, ld24, seth.
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "two_insn_const_operand" ""))]
|
||||
""
|
||||
[(set (match_dup 0) (match_dup 2))
|
||||
(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))]
|
||||
"
|
||||
{
|
||||
unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
|
||||
unsigned HOST_WIDE_INT tmp;
|
||||
int shift;
|
||||
|
||||
/* In all cases we will emit two instructions. However we try to
|
||||
use 2 byte instructions whereever possible. We can assume the
|
||||
constant isn't loadable with any of ldi, ld24, or seth. */
|
||||
|
||||
/* See if we can load a 24 bit unsigned value and invert it. */
|
||||
if (UINT24_P (~ val))
|
||||
{
|
||||
emit_insn (gen_movsi (operands[0], GEN_INT (~ val)));
|
||||
emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
|
||||
DONE;
|
||||
}
|
||||
|
||||
/* See if we can load a 24 bit unsigned value and shift it into place.
|
||||
0x01fffffe is just beyond ld24's range. */
|
||||
for (shift = 1, tmp = 0x01fffffe;
|
||||
shift < 8;
|
||||
++shift, tmp <<= 1)
|
||||
{
|
||||
if ((val & ~tmp) == 0)
|
||||
{
|
||||
emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift)));
|
||||
emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift)));
|
||||
DONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Can't use any two byte insn, fall back to seth/or3. */
|
||||
operands[2] = GEN_INT ((val) & 0xffff0000);
|
||||
operands[3] = GEN_INT ((val) & 0xffff);
|
||||
}")
|
||||
|
||||
;; Small data area support.
|
||||
;; The address of _SDA_BASE_ is loaded into a register and all objects in
|
||||
;; the small data area are indexed off that. This is done for each reference
|
||||
@ -769,7 +817,7 @@
|
||||
""
|
||||
"@
|
||||
and %0,%2
|
||||
and3 %0,%1,%#%2"
|
||||
and3 %0,%1,%#%2 ; %X2"
|
||||
[(set_attr "type" "binary")])
|
||||
|
||||
(define_insn "iorsi3"
|
||||
@ -779,7 +827,7 @@
|
||||
""
|
||||
"@
|
||||
or %0,%2
|
||||
or3 %0,%1,%#%2"
|
||||
or3 %0,%1,%#%2 ; %X2"
|
||||
[(set_attr "type" "binary")])
|
||||
|
||||
(define_insn "xorsi3"
|
||||
@ -789,7 +837,7 @@
|
||||
""
|
||||
"@
|
||||
xor %0,%2
|
||||
xor3 %0,%1,%#%2"
|
||||
xor3 %0,%1,%#%2 ; %X2"
|
||||
[(set_attr "type" "binary")])
|
||||
|
||||
(define_insn "negsi2"
|
||||
|
Loading…
Reference in New Issue
Block a user