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:
Doug Evans 1997-04-11 20:48:54 +00:00
parent 4e007b6eea
commit 4d6c607f2e
3 changed files with 87 additions and 11 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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"