Article View: gnu.gcc.help
Article #52398Help needed -- stack machine, no pre_dec addressing
From: Michael Gersten
Date: Sat, 17 Oct 1992 19:23
Date: Sat, 17 Oct 1992 19:23
163 lines
5459 bytes
5459 bytes
I have a machine with a stack, and no pre_decrement addressing other than
stack pushes, that I cannot get gcc to compile code for.
Originally, I had no pre_dec's in my md file, nor did I have #define
HAVE_PRE_DECREMENT. But I discovered while compiling __muldi3 that gcc assumes
it can use a pre_dec to push stack operands. So I added
(define_insn ""
[ (set (mem:HI (pre_dec:HI (reg:HI 15)))
(match_operand:HI 0 "general_operand" "r")
)]
""
" PSHM %0,%0"
)
(define_insn ""
[ (set (mem:SI (pre_dec:HI (reg:HI 15)))
(match_operand:SI 0 "general_operand" "r")
)]
""
"*
int r=REGNO(operands[0]);
char *s=alloca(200);
char *t;
sprintf(s, \" PSHM R%d,R%d\", r, r+1);
t = strdup(s);
return t;
"
)
to my md, and then __muldi3 was compiled fine.
The next routine in the library, __divdi3, was not so nice. After removing the
inline call to __negdi2 (just declaring it external), I had in my .rtl dump
(first pass)
(insn 31 30 32 (set (mem:HI (pre_dec:HI (reg:HI 15)))
(mem/s:HI (plus:HI (reg:HI 17)
(const_int -6)))) -1 (nil)
(nil))
which isn't a problem -- compile it as
(set (scratch_reg) (mem/s:HI (plus:HI (reg:HI 17)
(const_int -6))))
(set (mem:HI (pre_dec:HI (reg:HI 15))) (scratch_reg))
Except that GO_IF_LEGITIMATE_ADDRESS was passed things like:
Debug: Leg Addr failed for
(plus:HI (pre_dec:HI (reg:HI 15))
(const_int 1))
After the (const_int 1), came (const_int 2), (const_int 3),
and then it repeated about 20 times. Note that at this point,
HAVE_PRE_DECREMENT was still false, and the only places that pre_dec appeared
in the md file was in an unnamed pattern solely to match stack pushes.
Ultimately, it crashed with
x-temp.c: In function `__divdi3':
x-temp.c:102: internal error--unrecognizable insn:
(insn 32 31 33 (set (reg:HI 25)
(pre_dec:HI (reg:HI 15))) -1 (nil)
(nil))
I then modified GO_IF_LEGITIMATE_ADDRESS to accept an address consisting of
(pre_dec (reg 15)), thinking that maybe that was the problem (note that it
never produced a "not matched" debugging complaint), and also defined
HAVE_PRE_DECREMENT.
The result was still the same:
Debug: Leg Addr failed for
(plus:HI (pre_dec:HI (reg:HI 15))
(const_int 1))
....
x-temp.c: In function `__divdi3':
x-temp.c:102: internal error--unrecognizable insn:
(insn 32 31 33 (set (reg:HI 25)
(pre_dec:HI (reg:HI 15))) -1 (nil)
(nil))
It seems that the compiler, faced with computing (push (r17-6)), instead of
computing (x=(r17-6), push x) is instead computing
(get_addr(push), (addr) = (r17-6)).
Here is the .i file that was feed to cc1:
enum reg_class { NO_REGS, INDEX_REG,
BASE_INDEX_REG, R2_REG, ALL_REGS,
LIM_REG_CLASSES};
enum mode_types { R_mode, B_mode, BX_mode, ISP_mode, ISN_mode,
D_mode, DX_mode, IM_mode, IMX_mode, I_mode, IX_mode };
typedef enum mode_types mode_types;
extern struct rtx_def * gen_beq ();
extern struct rtx_def * gen_bne ();
extern struct rtx_def * gen_bgt ();
extern struct rtx_def * gen_bgtu ();
extern struct rtx_def * gen_blt ();
extern struct rtx_def * gen_bltu ();
extern struct rtx_def * gen_bge ();
extern struct rtx_def * gen_bgeu ();
extern struct rtx_def * gen_ble ();
extern struct rtx_def * gen_bleu ();
extern int strict_test;
extern mode_types what_mode();
extern enum reg_class regno_reg_class[];
extern char *make1Ins(struct rtx_def * [], char *, int);
extern char *make2Ins(struct rtx_def * [], char *, int);
extern char *makeIns(struct rtx_def * [], char *, int, char *);
extern char *makeCompare(struct rtx_def * , struct rtx_def * [], char *, int);
extern char *strdup(char *);
typedef long int ptrdiff_t;
typedef long unsigned int size_t;
typedef int wchar_t;
struct longlong {long high, low;};
typedef union
{
struct longlong s;
long long ll;
} long_long;
extern const unsigned char __clz_tab[];
extern long long __fixunssfdi (float a);
extern long long __fixunsdfdi (double a);
extern long long __negdi2 (long long u);
unsigned long long __udivmoddi4 ();
long long
__divdi3 (u, v)
long long u, v;
{
int c = 0;
long_long uu, vv;
long long w;
uu.ll = u;
vv.ll = v;
if (uu.s.high < 0)
c = ~c,
uu.ll = __negdi2 (uu.ll);
if (vv.s.high < 0)
c = ~c,
vv.ll = __negdi2 (vv.ll);
w = __udivmoddi4 (uu.ll, vv.ll, (unsigned long long *) 0);
if (c)
w = __negdi2 (w);
return w;
}
--
Michael Gersten michael@stb.info.com
HELLO! I'm a signature virus! Join in the fun and copy me into yours!
ex:.-1,. w $HOME/.signature
Technical Details
Message-ID:
<m0mgJk6-0005OXC@stb.info.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!stb.INfo.COM!michaelShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 11318c,d4ac29d1a57cd888,start X-Google-Attributes: gid11318c,public X-Google-ArrivalTime: 1992-10-17 07:53:52 PST Newsgroups: gnu.gcc.help Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!stb.INfo.COM!michael From: michael@stb.INfo.COM (Michael Gersten) Subject: Help needed -- stack machine, no pre_dec addressing Message-ID: <m0mgJk6-0005OXC@stb.info.com> Sender: daemon@cis.ohio-state.edu Organization: GNUs Not Usenet Distribution: gnu Date: Sat, 17 Oct 1992 19:23:00 GMT Lines: 163