ack/mach/m68020/ncg/mach.c

345 lines
6.2 KiB
C
Raw Normal View History

1987-03-10 11:49:39 +00:00
/* $Header$ */
1987-01-13 09:24:13 +00:00
/*
1987-03-10 01:26:51 +00:00
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
1987-01-13 09:24:13 +00:00
*
*/
/*
* machine dependent back end routines for the Motorola 68000, 68010 or 68020
*/
#include "whichone.h"
1987-01-13 09:24:13 +00:00
con_part(sz,w) register sz; word w; {
while (part_size % sz)
part_size++;
if (part_size == 4)
part_flush();
if (sz == 1) {
w &= 0xFF;
w <<= 8*(3-part_size);
part_word |= w;
} else if (sz == 2) {
w &= 0xFFFF;
if (part_size == 0)
w <<= 16;
part_word |= w;
} else {
assert(sz == 4);
part_word = w;
}
part_size += sz;
}
con_mult(sz) word sz; {
if (sz != 4)
fatal("bad icon/ucon size");
fprintf(codefile,".data4 %s\n",str);
}
#ifdef NOFLOAT
1987-01-13 09:24:13 +00:00
con_float() {
static int been_here;
if (argval != 4 && argval != 8)
fatal("bad fcon size");
fputs(".data4\t", codefile);
1987-01-13 09:24:13 +00:00
if (argval == 8)
fputs("0,", codefile);
fputs("0 !dummy float\n", codefile);
1987-01-13 09:24:13 +00:00
if ( !been_here++)
{
fputs("Warning : dummy float-constant(s)\n", stderr);
1987-01-13 09:24:13 +00:00
}
}
#else
1989-06-12 09:30:39 +00:00
#if TBL68881
#define OWNFLOAT
#else
#define IEEEFLOAT
1989-06-12 09:30:39 +00:00
#endif
con_float() {
double f;
double atof();
int i;
int j;
1988-04-28 14:46:11 +00:00
double frexp();
#ifndef OWNFLOAT
int sign = 0;
int fraction[4] ;
#else OWNFLOAT
1988-03-31 10:38:05 +00:00
float fl;
char *p;
#endif OWNFLOAT
if (argval!= 4 && argval!= 8) {
1989-02-02 16:32:19 +00:00
fprintf(stderr,"float constant size = %ld\n",argval);
fatal("bad fcon size");
}
1989-02-02 16:32:19 +00:00
fprintf(codefile,"!float %s sz %ld\n", str, argval);
f = atof(str);
1988-04-28 14:46:11 +00:00
if (f == 0) {
if (argval == 8) fprintf(codefile, ".data2 0, 0\n");
fprintf(codefile, ".data2 0, 0\n");
return;
}
#ifdef OWNFLOAT
if (argval == 4) {
1988-04-28 14:46:11 +00:00
/* careful: avoid overflow */
double ldexp();
f = frexp(f, &i);
fl = f;
1988-04-28 14:46:11 +00:00
fl = frexp(fl,&j);
if (i+j > 127) {
/* overflow situation */
fprintf(codefile, ".data1 0%o, 0377, 0377, 0377 ! overflow\n",
f < 0 ? 0377 : 0177);
return;
}
if (i+j < -127) {
/* underflow situation */
fprintf(codefile, ".data1 0%o, 0200, 0, 0 ! underflow\n",
f < 0 ? 0200 : 0);
return;
}
fl = ldexp(fl, i+j);
p = (char *) &fl;
}
else {
p = (char *) &f;
}
fprintf(codefile, ".data1 0%o", *p++ & 0377);
1987-11-06 13:12:21 +00:00
for (i = argval-1; i; i--) {
fprintf(codefile,",0%o", *p++ & 0377);
}
#else OWNFLOAT
f = frexp(f, &i);
if (f < 0) {
f = -f;
sign = 1;
}
while (f < 0.5) {
f += f;
i --;
}
1988-04-22 14:11:55 +00:00
f = 2*f - 1.0; /* hidden bit */
#ifdef IEEEFLOAT
if (argval == 4) {
#endif IEEEFLOAT
i = (i + 128) & 0377;
fraction[0] = (sign << 15) | (i << 7);
for (j = 6; j>= 0; j--) {
1988-04-22 14:11:55 +00:00
f *= 2;
if (f >= 1.0) {
f -= 1.0;
fraction[0] |= (1 << j);
}
}
#ifdef IEEEFLOAT
}
else {
i = (i + 1024) & 03777;
fraction[0] = (sign << 15) | (i << 4);
for (j = 3; j>= 0; j--) {
1988-04-22 14:11:55 +00:00
f *= 2;
if (f >= 1.0) {
fraction[0] |= (1 << j);
f -= 1.0;
}
}
}
#endif IEEEFLOAT
for (i = 1; i < argval / 2; i++) {
fraction[i] = 0;
for (j = 15; j>= 0; j--) {
1988-04-22 14:11:55 +00:00
f *= 2;
if (f >= 1.0) {
fraction[i] |= (1 << j);
f -= 1.0;
}
}
}
if (f >= 0.5) {
for (i = argval/2 - 1; i >= 0; i--) {
for (j = 0; j < 16; j++) {
if (fraction[i] & (1 << j)) {
fraction[i] &= ~(1 << j);
}
else {
fraction[i] |= (1 << j);
break;
}
}
if (j != 16) break;
}
}
for (i = 0; i < argval/2; i++) {
fprintf(codefile,
i != 0 ? ", 0%o, 0%o" : ".data1 0%o, 0%o",
(fraction[i]>>8)&0377,
fraction[i]&0377);
}
#endif OWNFLOAT
putc('\n', codefile);
}
#endif
1987-01-13 09:24:13 +00:00
regscore(off,size,typ,score,totyp)
long off;
{
if (score == 0) return -1;
switch(typ) {
case reg_float:
return -1;
case reg_pointer:
if (size != 4 || totyp != reg_pointer) return -1;
1987-08-12 16:19:02 +00:00
score += (score >> 1);
1987-01-13 09:24:13 +00:00
break;
case reg_loop:
score += 5;
/* fall through .. */
case reg_any:
if (size != 4 || totyp == reg_pointer) return -1;
break;
}
if (off >= 0) {
/* parameters must be initialised with an instruction
* like "move.l 4(a6),d0", which costs 2 words.
*/
score -= 2;
}
1987-08-12 16:19:02 +00:00
score--; /* save/restore */
1987-01-13 09:24:13 +00:00
return score;
}
struct regsav_t {
char *rs_reg; /* e.g. "a3" or "d5" */
long rs_off; /* offset of variable */
int rs_size; /* 2 or 4 bytes */
} regsav[9];
int regnr;
i_regsave()
{
regnr = 0;
}
full nlocals;
regreturn()
{
register struct regsav_t *p;
if (regnr > 1) {
1989-02-22 17:38:07 +00:00
#ifdef TBL68020
fprintf(codefile,"movem.l (-%ld,a6),", nlocals);
#else
fprintf(codefile,"movem.l -%ld(a6),", nlocals);
1989-02-22 17:38:07 +00:00
#endif
for (p = regsav; ;) {
fputs(p->rs_reg, codefile);
if (++p == &regsav[regnr]) break;
putc('/',codefile);
}
putc('\n',codefile);
} else if (regnr == 1) {
1989-02-22 17:38:07 +00:00
p = regsav;
#ifdef TBL68020
fprintf(codefile,"move.l (-%ld,a6),%s\n",nlocals, p->rs_reg);
#else
fprintf(codefile,"move.l -%ld(a6),%s\n",nlocals, p->rs_reg);
#endif
}
fputs("unlk a6\nrts\n", codefile);
}
f_regsave()
1987-01-13 09:24:13 +00:00
{
register struct regsav_t *p;
nlocals += regnr*4;
#ifdef TBL68020
fprintf(codefile,"link\ta6,#-%ld\n",nlocals);
#else
fprintf(codefile,"tst.b -%ld(sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals);
#endif
if (regnr > 1) {
fputs("movem.l ", codefile);
1987-01-13 09:24:13 +00:00
for (p = regsav; ;) {
fputs(p->rs_reg, codefile);
1987-01-13 09:24:13 +00:00
if (++p == &regsav[regnr]) break;
putc('/',codefile);
}
fputs(",(sp)\n", codefile);
} else if (regnr == 1) {
1989-02-22 17:38:07 +00:00
p = regsav;
fprintf(codefile,"move.l %s,(sp)\n",p->rs_reg);
1987-01-13 09:24:13 +00:00
}
/* initialise register-parameters */
for (p = regsav; p < &regsav[regnr]; p++) {
if (p->rs_off >= 0) {
#ifdef TBL68020
1987-01-13 09:24:13 +00:00
fprintf(codefile,"move.%c (%ld,a6),%s\n",
#else
fprintf(codefile,"move.%c %ld(a6),%s\n",
#endif
(p->rs_size == 4 ? 'l' : 'w'),
p->rs_off,
p->rs_reg);
}
}
}
1988-03-31 10:38:05 +00:00
regsave(s,off,size)
char *s;
1987-01-13 09:24:13 +00:00
long off;
{
assert (regnr < 9);
1988-03-31 10:38:05 +00:00
regsav[regnr].rs_reg = s;
1987-01-13 09:24:13 +00:00
regsav[regnr].rs_off = off;
regsav[regnr++].rs_size = size;
1988-03-31 10:38:05 +00:00
fprintf(codefile, "!Local %ld into %s\n",off,s);
1987-01-13 09:24:13 +00:00
}
prolog(n) full n; {
1987-01-13 09:24:13 +00:00
nlocals = n;
1987-01-13 09:24:13 +00:00
}
mes(type) word type ; {
int argt ;
switch ( (int)type ) {
case ms_ext :
for (;;) {
switch ( argt=getarg(
ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) ) {
case sp_cend :
return ;
default:
strarg(argt) ;
fprintf(codefile,".define %s\n",argstr) ;
break ;
}
}
default :
while ( getarg(any_ptyp) != sp_cend ) ;
break ;
}
}
char *segname[] = {
".sect .text", /* SEGTXT */
".sect .data", /* SEGCON */
".sect .rom", /* SEGROM */
".sect .bss" /* SEGBSS */
};