add arm vfp support to compiler and linker (from sources)
This commit is contained in:
parent
bc610a1b1c
commit
ea0f580909
|
@ -102,6 +102,9 @@ and
|
|||
.L _traceout
|
||||
at function exits.
|
||||
.TP
|
||||
.B -f
|
||||
(ARM only) Generate VFP hardware floating point instructions.
|
||||
.TP
|
||||
.B -s
|
||||
Strip the symbol tables from the output file.
|
||||
.TP
|
||||
|
|
|
@ -721,8 +721,13 @@ gmove(Node *f, Node *t)
|
|||
regfree(&nod1);
|
||||
p1 = p;
|
||||
regalloc(&nod, t, Z);
|
||||
gins(AMOVF, nodfconst(2147483648.), &nod);
|
||||
gins(AADDF, &nod, t);
|
||||
if(tt == TFLOAT) {
|
||||
gins(AMOVF, nodfconst(2147483648.), &nod);
|
||||
gins(AADDF, &nod, t);
|
||||
} else {
|
||||
gins(AMOVD, nodfconst(2147483648.), &nod);
|
||||
gins(AADDD, &nod, t);
|
||||
}
|
||||
regfree(&nod);
|
||||
patch(p1, pc);
|
||||
return;
|
||||
|
@ -1056,7 +1061,8 @@ gopcode(int o, Node *f1, Node *f2, Node *t)
|
|||
nextpc();
|
||||
p->as = a;
|
||||
naddr(f1, &p->from);
|
||||
if(a == ACMP && f1->op == OCONST && p->from.offset < 0 && p->from.offset != -p->from.offset) {
|
||||
if(a == ACMP && f1->op == OCONST && p->from.offset < 0 &&
|
||||
p->from.offset != 0x80000000) {
|
||||
p->as = ACMN;
|
||||
p->from.offset = -p->from.offset;
|
||||
}
|
||||
|
|
|
@ -483,12 +483,12 @@ asmlc(void)
|
|||
if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(debug['L'])
|
||||
if(debug['V'])
|
||||
Bprint(&bso, "%6lux %P\n",
|
||||
p->pc, p);
|
||||
continue;
|
||||
}
|
||||
if(debug['L'])
|
||||
if(debug['V'])
|
||||
Bprint(&bso, "\t\t%6ld", lcsize);
|
||||
v = (p->pc - oldpc) / MINLC;
|
||||
while(v) {
|
||||
|
@ -496,7 +496,7 @@ asmlc(void)
|
|||
if(v < 127)
|
||||
s = v;
|
||||
cput(s+128); /* 129-255 +pc */
|
||||
if(debug['L'])
|
||||
if(debug['V'])
|
||||
Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
|
||||
v -= s;
|
||||
lcsize++;
|
||||
|
@ -510,7 +510,7 @@ asmlc(void)
|
|||
cput(s>>16);
|
||||
cput(s>>8);
|
||||
cput(s);
|
||||
if(debug['L']) {
|
||||
if(debug['V']) {
|
||||
if(s > 0)
|
||||
Bprint(&bso, " lc+%ld(%d,%ld)\n",
|
||||
s, 0, s);
|
||||
|
@ -525,14 +525,14 @@ asmlc(void)
|
|||
}
|
||||
if(s > 0) {
|
||||
cput(0+s); /* 1-64 +lc */
|
||||
if(debug['L']) {
|
||||
if(debug['V']) {
|
||||
Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
|
||||
Bprint(&bso, "%6lux %P\n",
|
||||
p->pc, p);
|
||||
}
|
||||
} else {
|
||||
cput(64-s); /* 65-128 -lc */
|
||||
if(debug['L']) {
|
||||
if(debug['V']) {
|
||||
Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
|
||||
Bprint(&bso, "%6lux %P\n",
|
||||
p->pc, p);
|
||||
|
@ -545,7 +545,7 @@ asmlc(void)
|
|||
cput(s);
|
||||
lcsize++;
|
||||
}
|
||||
if(debug['v'] || debug['L'])
|
||||
if(debug['v'] || debug['V'])
|
||||
Bprint(&bso, "lcsize = %ld\n", lcsize);
|
||||
Bflush(&bso);
|
||||
}
|
||||
|
@ -1365,6 +1365,53 @@ PP = p;
|
|||
else if(p->as == AMOVH)
|
||||
o2 ^= (1<<6);
|
||||
break;
|
||||
|
||||
/* VFP ops: */
|
||||
case 74: /* vfp floating point arith */
|
||||
o1 = opvfprrr(p->as, p->scond);
|
||||
rf = p->from.reg;
|
||||
if(p->from.type == D_FCONST) {
|
||||
diag("invalid floating-point immediate\n%P", p);
|
||||
rf = 0;
|
||||
}
|
||||
rt = p->to.reg;
|
||||
r = p->reg;
|
||||
if(r == NREG)
|
||||
r = rt;
|
||||
o1 |= rt<<12;
|
||||
if(((o1>>20)&0xf) == 0xb)
|
||||
o1 |= rf<<0;
|
||||
else
|
||||
o1 |= r<<16 | rf<<0;
|
||||
break;
|
||||
case 75: /* vfp floating point compare */
|
||||
o1 = opvfprrr(p->as, p->scond);
|
||||
rf = p->from.reg;
|
||||
if(p->from.type == D_FCONST) {
|
||||
if(p->from.ieee->h != 0 || p->from.ieee->l != 0)
|
||||
diag("invalid floating-point immediate\n%P", p);
|
||||
o1 |= 1<<16;
|
||||
rf = 0;
|
||||
}
|
||||
rt = p->reg;
|
||||
o1 |= rt<<12 | rf<<0;
|
||||
o2 = 0x0ef1fa10; /* MRS APSR_nzcv, FPSCR */
|
||||
o2 |= (p->scond & C_SCOND) << 28;
|
||||
break;
|
||||
case 76: /* vfp floating point fix and float */
|
||||
o1 = opvfprrr(p->as, p->scond);
|
||||
rf = p->from.reg;
|
||||
rt = p->to.reg;
|
||||
if(p->from.type == D_REG) {
|
||||
o2 = o1 | rt<<12 | rt<<0;
|
||||
o1 = 0x0e000a10; /* VMOV F,R */
|
||||
o1 |= (p->scond & C_SCOND) << 28 | rt<<16 | rf<<12;
|
||||
} else {
|
||||
o1 |= FREGTMP<<12 | rf<<0;
|
||||
o2 = 0x0e100a10; /* VMOV R,F */
|
||||
o2 |= (p->scond & C_SCOND) << 28 | FREGTMP<<16 | rt<<12;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(debug['a'] > 1)
|
||||
|
@ -1493,6 +1540,40 @@ oprrr(int a, int sc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
opvfprrr(int a, int sc)
|
||||
{
|
||||
long o;
|
||||
|
||||
o = (sc & C_SCOND) << 28;
|
||||
if(sc & (C_SBIT|C_PBIT|C_WBIT))
|
||||
diag(".S/.P/.W on vfp instruction");
|
||||
o |= 0xe<<24;
|
||||
switch(a) {
|
||||
case AMOVWD: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x8<<16 | 1<<7;
|
||||
case AMOVWF: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x8<<16 | 1<<7;
|
||||
case AMOVDW: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0xD<<16 | 1<<7;
|
||||
case AMOVFW: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0xD<<16 | 1<<7;
|
||||
case AMOVFD: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x7<<16 | 1<<7;
|
||||
case AMOVDF: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x7<<16 | 1<<7;
|
||||
case AMOVF: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x0<<16 | 0<<7;
|
||||
case AMOVD: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x0<<16 | 0<<7;
|
||||
case ACMPF: return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x4<<16 | 0<<7;
|
||||
case ACMPD: return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x4<<16 | 0<<7;
|
||||
case AADDF: return o | 0xa<<8 | 0x3<<20;
|
||||
case AADDD: return o | 0xb<<8 | 0x3<<20;
|
||||
case ASUBF: return o | 0xa<<8 | 0x3<<20 | 1<<6;
|
||||
case ASUBD: return o | 0xb<<8 | 0x3<<20 | 1<<6;
|
||||
case AMULF: return o | 0xa<<8 | 0x2<<20;
|
||||
case AMULD: return o | 0xb<<8 | 0x2<<20;
|
||||
case ADIVF: return o | 0xa<<8 | 0x8<<20;
|
||||
case ADIVD: return o | 0xb<<8 | 0x8<<20;
|
||||
}
|
||||
diag("bad vfp rrr %d", a);
|
||||
prasm(curp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
opbra(int a, int sc)
|
||||
{
|
||||
|
@ -1627,11 +1708,46 @@ olhrr(int i, int b, int r, int sc)
|
|||
return olhr(i, b, r, sc) ^ (1<<22);
|
||||
}
|
||||
|
||||
long
|
||||
ovfpmem(int a, int r, long v, int b, int sc, Prog *p)
|
||||
{
|
||||
long o;
|
||||
|
||||
if(sc & (C_SBIT|C_PBIT|C_WBIT))
|
||||
diag(".S/.P/.W on VLDR/VSTR instruction");
|
||||
o = (sc & C_SCOND) << 28;
|
||||
o |= 0xd<<24 | (1<<23);
|
||||
if(v < 0) {
|
||||
v = -v;
|
||||
o ^= 1 << 23;
|
||||
}
|
||||
if(v & 3)
|
||||
diag("odd offset for floating point op: %ld\n%P", v, p);
|
||||
else if(v >= (1<<10))
|
||||
diag("literal span too large: %ld\n%P", v, p);
|
||||
o |= (v>>2) & 0xFF;
|
||||
o |= b << 16;
|
||||
o |= r << 12;
|
||||
switch(a) {
|
||||
default:
|
||||
diag("bad fst %A", a);
|
||||
case AMOVD:
|
||||
o |= 0xb<<8;
|
||||
break;
|
||||
case AMOVF:
|
||||
o |= 0xa<<8;
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
long
|
||||
ofsr(int a, int r, long v, int b, int sc, Prog *p)
|
||||
{
|
||||
long o;
|
||||
|
||||
if(vfp)
|
||||
return ovfpmem(a, r, v, b, sc, p);
|
||||
if(sc & C_SBIT)
|
||||
diag(".S on FLDR/FSTR instruction");
|
||||
o = (sc & C_SCOND) << 28;
|
||||
|
@ -1703,6 +1819,8 @@ chipfloat(Ieee *e)
|
|||
Ieee *p;
|
||||
int n;
|
||||
|
||||
if(vfp)
|
||||
return -1;
|
||||
for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){
|
||||
p = &chipfloats[n];
|
||||
if(p->l == e->l && p->h == e->h)
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define LIBNAMELEN 300
|
||||
|
||||
void addlibpath(char*);
|
||||
int fileexists(char*);
|
||||
char* findlib(char*);
|
||||
|
||||
typedef struct Adr Adr;
|
||||
typedef struct Sym Sym;
|
||||
|
@ -134,6 +139,7 @@ enum
|
|||
LTO = 1<<1,
|
||||
LPOOL = 1<<2,
|
||||
V4 = 1<<3, /* arm v4 arch */
|
||||
VFP = 1<<4, /* arm vfpv3 floating point */
|
||||
|
||||
C_NONE = 0,
|
||||
C_REG,
|
||||
|
@ -269,6 +275,7 @@ EXTERN char xcmp[C_GOK+1][C_GOK+1];
|
|||
EXTERN Prog zprg;
|
||||
EXTERN int dtype;
|
||||
EXTERN int armv4;
|
||||
EXTERN int vfp;
|
||||
|
||||
EXTERN int doexp, dlm;
|
||||
EXTERN int imports, nimports;
|
||||
|
@ -309,6 +316,7 @@ int Pconv(Fmt*);
|
|||
int Sconv(Fmt*);
|
||||
int aclass(Adr*);
|
||||
void addhist(long, int);
|
||||
void addlibpath(char*);
|
||||
void append(Prog*, Prog*);
|
||||
void asmb(void);
|
||||
void asmdyn(void);
|
||||
|
@ -336,7 +344,9 @@ long entryvalue(void);
|
|||
void errorexit(void);
|
||||
void exchange(Prog*);
|
||||
void export(void);
|
||||
int fileexists(char*);
|
||||
int find1(long, int);
|
||||
char* findlib(char*);
|
||||
void follow(void);
|
||||
void gethunk(void);
|
||||
void histtoauto(void);
|
||||
|
@ -361,6 +371,7 @@ int ocmp(const void*, const void*);
|
|||
long opirr(int);
|
||||
Optab* oplook(Prog*);
|
||||
long oprrr(int, int);
|
||||
long opvfprrr(int, int);
|
||||
long olr(long, int, int, int);
|
||||
long olhr(long, int, int, int);
|
||||
long olrr(int, int, int, int);
|
||||
|
|
|
@ -302,6 +302,30 @@ noops(void)
|
|||
|
||||
break;
|
||||
|
||||
/*
|
||||
* 5c code generation for unsigned -> double made the
|
||||
* unfortunate assumption that single and double floating
|
||||
* point registers are aliased - true for emulated 7500
|
||||
* but not for vfp. Now corrected, but this test is
|
||||
* insurance against old 5c compiled code in libraries.
|
||||
*/
|
||||
case AMOVWD:
|
||||
if((q = p->link) != P && q->as == ACMP)
|
||||
if((q = q->link) != P && q->as == AMOVF)
|
||||
if((q1 = q->link) != P && q1->as == AADDF)
|
||||
if(q1->to.type == D_FREG && q1->to.reg == p->to.reg) {
|
||||
q1->as = AADDD;
|
||||
q1 = prg();
|
||||
q1->scond = q->scond;
|
||||
q1->line = q->line;
|
||||
q1->as = AMOVFD;
|
||||
q1->from = q->to;
|
||||
q1->to = q1->from;
|
||||
q1->link = q->link;
|
||||
q->link = q1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ADIV:
|
||||
case ADIVU:
|
||||
case AMOD:
|
||||
|
|
|
@ -211,6 +211,14 @@ Optab optab[] =
|
|||
{ ACASE, C_REG, C_NONE, C_NONE, 62, 4, 0 },
|
||||
{ ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0 },
|
||||
|
||||
{ AADDF, C_FREG, C_NONE, C_FREG, 74, 4, 0, VFP },
|
||||
{ AADDF, C_FREG, C_REG, C_FREG, 74, 4, 0, VFP },
|
||||
{ AMOVF, C_FREG, C_NONE, C_FREG, 74, 4, 0, VFP },
|
||||
{ ACMPF, C_FREG, C_REG, C_NONE, 75, 8, 0, VFP },
|
||||
{ ACMPF, C_FCON, C_REG, C_NONE, 75, 8, 0, VFP },
|
||||
{ AMOVFW, C_FREG, C_NONE, C_REG, 76, 8, 0, VFP },
|
||||
{ AMOVFW, C_REG, C_NONE, C_FREG, 76, 8, 0, VFP },
|
||||
|
||||
{ AMOVH, C_REG, C_NONE, C_HEXT, 70, 4, REGSB, V4 },
|
||||
{ AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, V4 },
|
||||
{ AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, V4 },
|
||||
|
|
|
@ -637,6 +637,9 @@ ocmp(const void *a1, const void *a2)
|
|||
if(n)
|
||||
return n;
|
||||
n = (p2->flag&V4) - (p1->flag&V4); /* architecture version */
|
||||
if(n)
|
||||
return n;
|
||||
n = (p2->flag&VFP) - (p1->flag&VFP); /* floating point arch */
|
||||
if(n)
|
||||
return n;
|
||||
n = p1->a1 - p2->a1;
|
||||
|
@ -657,14 +660,18 @@ buildop(void)
|
|||
int i, n, r;
|
||||
|
||||
armv4 = !debug['h'];
|
||||
vfp = debug['f'];
|
||||
for(i=0; i<C_GOK; i++)
|
||||
for(n=0; n<C_GOK; n++)
|
||||
xcmp[i][n] = cmp(n, i);
|
||||
for(n=0; optab[n].as != AXXX; n++)
|
||||
for(n=0; optab[n].as != AXXX; n++) {
|
||||
if((optab[n].flag & VFP) && !vfp)
|
||||
optab[n].as = AXXX;
|
||||
if((optab[n].flag & V4) && !armv4) {
|
||||
optab[n].as = AXXX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qsort(optab, n, sizeof(optab[0]), ocmp);
|
||||
for(i=0; i<n; i++) {
|
||||
r = optab[i].as;
|
||||
|
@ -679,6 +686,8 @@ buildop(void)
|
|||
default:
|
||||
diag("unknown op in build: %A", r);
|
||||
errorexit();
|
||||
case AXXX:
|
||||
break;
|
||||
case AADD:
|
||||
oprange[AAND] = oprange[r];
|
||||
oprange[AEOR] = oprange[r];
|
||||
|
|
|
@ -135,7 +135,7 @@ char* addsub[2] =
|
|||
int
|
||||
armclass(long w)
|
||||
{
|
||||
int op, done;
|
||||
int op, done, cp;
|
||||
|
||||
op = (w >> 25) & 0x7;
|
||||
switch(op) {
|
||||
|
@ -220,8 +220,62 @@ armclass(long w)
|
|||
op = (48+24+4+4+2) + ((w >> 24) & 0x1);
|
||||
break;
|
||||
case 7: /* coprocessor crap */
|
||||
cp = (w >> 8) & 0xF;
|
||||
if(cp == 10 || cp == 11){ /* vfp */
|
||||
if((w >> 4) & 0x1){
|
||||
/* vfp register transfer */
|
||||
switch((w >> 21) & 0x7){
|
||||
case 0:
|
||||
op = 118 + ((w >> 20) & 0x1);
|
||||
break;
|
||||
case 7:
|
||||
op = 118+2 + ((w >> 20) & 0x1);
|
||||
break;
|
||||
default:
|
||||
op = (48+24+4+4+2+2+4+4);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* vfp data processing */
|
||||
if(((w >> 23) & 0x1) == 0){
|
||||
op = 100 + ((w >> 19) & 0x6) + ((w >> 6) & 0x1);
|
||||
break;
|
||||
}
|
||||
switch(((w >> 19) & 0x6) + ((w >> 6) & 0x1)){
|
||||
case 0:
|
||||
op = 108;
|
||||
break;
|
||||
case 7:
|
||||
if(((w >> 19) & 0x1) == 0)
|
||||
if(((w >> 17) & 0x1) == 0)
|
||||
op = 109 + ((w >> 16) & 0x4) +
|
||||
((w >> 15) & 0x2) +
|
||||
((w >> 7) & 0x1);
|
||||
else if(((w >> 16) & 0x7) == 0x7)
|
||||
op = 117;
|
||||
else
|
||||
switch((w >> 16) & 0x7){
|
||||
case 0:
|
||||
case 4:
|
||||
case 5:
|
||||
op = 117;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(op == 7)
|
||||
op = (48+24+4+4+2+2+4+4);
|
||||
break;
|
||||
}
|
||||
op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
|
||||
break;
|
||||
case 6: /* vfp load / store */
|
||||
if(((w >> 21) &0x9) == 0x8){
|
||||
op = 122 + ((w >> 20) & 0x1);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
op = (48+24+4+4+2+2+4+4);
|
||||
break;
|
||||
|
@ -298,7 +352,7 @@ plocal(Instr *i)
|
|||
* Print value v as name[+offset]
|
||||
*/
|
||||
static int
|
||||
gsymoff(char *buf, int n, long v, int space)
|
||||
gsymoff(char *buf, int n, ulong v, int space)
|
||||
{
|
||||
Symbol s;
|
||||
int r;
|
||||
|
@ -405,6 +459,20 @@ armsdti(Opcode *o, Instr *i)
|
|||
format(o->o, i, o->a);
|
||||
}
|
||||
|
||||
static void
|
||||
armvstdi(Opcode *o, Instr *i)
|
||||
{
|
||||
ulong v;
|
||||
|
||||
v = (i->w & 0xff) << 2;
|
||||
if(!(i->w & (1<<23)))
|
||||
v = -v;
|
||||
i->imm = v;
|
||||
i->rn = (i->w >> 16) & 0xf;
|
||||
i->rd = (i->w >> 12) & 0xf;
|
||||
format(o->o, i, o->a);
|
||||
}
|
||||
|
||||
/* arm V4 ld/st halfword, signed byte */
|
||||
static void
|
||||
armhwby(Opcode *o, Instr *i)
|
||||
|
@ -870,6 +938,40 @@ static Opcode opcodes[] =
|
|||
|
||||
/* 99 */
|
||||
"RFEV7%P%a", armbdt, 0, "(R%n)",
|
||||
|
||||
/* 100 */
|
||||
"MLA%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
"MLS%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
"NMLS%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
"NMLA%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
"MUL%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
"NMUL%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
"ADD%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
"SUB%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
"DIV%f%C", armdps, 0, "F%s,F%n,F%d",
|
||||
|
||||
/* 109 */
|
||||
"MOV%f%C", armdps, 0, "F%s,F%d",
|
||||
"ABS%f%C", armdps, 0, "F%s,F%d",
|
||||
"NEG%f%C", armdps, 0, "F%s,F%d",
|
||||
"SQRT%f%C", armdps, 0, "F%s,F%d",
|
||||
"CMP%f%C", armdps, 0, "F%s,F%d",
|
||||
"CMPE%f%C", armdps, 0, "F%s,F%d",
|
||||
"CMP%f%C", armdps, 0, "$0.0,F%d",
|
||||
"CMPE%f%C", armdps, 0, "$0.0,F%d",
|
||||
|
||||
/* 117 */
|
||||
"MOV%F%R%C", armdps, 0, "F%s,F%d",
|
||||
|
||||
/* 118 */
|
||||
"MOVW%C", armdps, 0, "R%d,F%n",
|
||||
"MOVW%C", armdps, 0, "F%n,R%d",
|
||||
"MOVW%C", armdps, 0, "R%d,%x",
|
||||
"MOVW%C", armdps, 0, "%x,R%d",
|
||||
|
||||
/* 122 */
|
||||
"MOV%f%C", armvstdi, 0, "F%d,%I",
|
||||
"MOV%f%C", armvstdi, 0, "%I,F%d",
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -1011,7 +1113,7 @@ format(char *mnemonic, Instr *i, char *f)
|
|||
|
||||
case 'b':
|
||||
i->curr += symoff(i->curr, i->end-i->curr,
|
||||
i->imm, CTEXT);
|
||||
(ulong)i->imm, CTEXT);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
|
@ -1019,6 +1121,68 @@ format(char *mnemonic, Instr *i, char *f)
|
|||
i->imm, CANY);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
switch((i->w >> 8) & 0xF){
|
||||
case 10:
|
||||
bprint(i, "F");
|
||||
break;
|
||||
case 11:
|
||||
bprint(i, "D");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
switch(((i->w >> 15) & 0xE) + ((i->w >> 8) & 0x1)){
|
||||
case 0x0:
|
||||
bprint(i, ((i->w >> 7) & 0x1)? "WF" : "WF.U");
|
||||
break;
|
||||
case 0x1:
|
||||
bprint(i, ((i->w >> 7) & 0x1)? "WD" : "WD.U");
|
||||
break;
|
||||
case 0x8:
|
||||
bprint(i, "FW.U");
|
||||
break;
|
||||
case 0x9:
|
||||
bprint(i, "DW.U");
|
||||
break;
|
||||
case 0xA:
|
||||
bprint(i, "FW");
|
||||
break;
|
||||
case 0xB:
|
||||
bprint(i, "DW");
|
||||
break;
|
||||
case 0xE:
|
||||
bprint(i, "FD");
|
||||
break;
|
||||
case 0xF:
|
||||
bprint(i, "DF");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
if(((i->w >> 7) & 0x1) == 0)
|
||||
bprint(i, "R");
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
switch(i->rn){
|
||||
case 0:
|
||||
bprint(i, "FPSID");
|
||||
break;
|
||||
case 1:
|
||||
bprint(i, "FPSCR");
|
||||
break;
|
||||
case 2:
|
||||
bprint(i, "FPEXC");
|
||||
break;
|
||||
default:
|
||||
bprint(i, "FPS(%d)", i->rn);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
n = i->imm&0xffff;
|
||||
j = 0;
|
||||
|
|
Loading…
Reference in a new issue