ref: ecb298419235bf5721db7e37e91af2d4c28bc783
parent: a9f4ddade4bb5658b19097a11d139265d57b9748
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Thu Sep 7 11:04:56 EDT 2023
7l: support fused multiply-add/sub ops
--- a/sys/src/cmd/7l/asmout.c
+++ b/sys/src/cmd/7l/asmout.c
@@ -24,6 +24,7 @@
#define FPCCMP(m,s,type,op) ((m)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | 1<<10 | (op)<<4)
#define FPOP1S(m,s,type,op) ((m)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | (op)<<15 | 0x10<<10)
#define FPOP2S(m,s,type,op) ((m)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | (op)<<12 | 2<<10)
+#define FPOP3S(type,op,op2) (0x1F<<24 | (type)<<22 | (op2)<<21 | (op)<<15)
#define FPCVTI(sf,s,type,rmode,op) ((sf)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 1<<21 | (rmode)<<19 | (op)<<16 | 0<<10)
#define FPCVTF(sf,s,type,rmode,op,scale) ((sf)<<31 | (s)<<29 | 0x1E<<24 | (type)<<22 | 0<<21 | (rmode)<<19 | (op)<<16 | (scale)<<10)
#define ADR(p,o,rt) ((p)<<31 | ((o)&3)<<29 | (0x10<<24) | (((o>>2)&0x7FFFF)<<5) | (rt))
@@ -247,7 +248,7 @@
o1 = instoffset;
break;
- case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Rn,Ra,Rd */
+ case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Rn,[Ra,]Rd */
o1 = oprrr(p->as);
rf = p->from.reg;
rt = p->to.reg;
@@ -893,6 +894,17 @@
o1 = LD2STR(olsxrr(p->as, v&31, p->to.reg, p->from.reg));
o1 |= ((v>>8)&7)<<13 | ((v>>16)&1)<<12;
break;
+
+ case 70: /* fmadd/fmsub Rm,Rn,[Ra,]Rd */
+ o1 = oprrr(p->as);
+ rf = p->from.reg;
+ rt = p->to.reg;
+ r = p->from3.reg;
+ ra = p->reg;
+ if(ra == NREG)
+ ra = rt;
+ o1 |= (rf<<16) | (ra<<10) | (r<<5) | rt;
+ break;
}
if(debug['a'] > 1)
@@ -1149,8 +1161,17 @@
case AFMAXNMD: return FPOP2S(0, 0, 1, 6);
case AFMINNMS: return FPOP2S(0, 0, 0, 7);
case AFMINNMD: return FPOP2S(0, 0, 1, 7);
- case AFNMULS: return FPOP2S(0, 0, 0, 8);
+ case AFNMULS: return FPOP2S(0, 0, 0, 8);
case AFNMULD: return FPOP2S(0, 0, 1, 8);
+
+ case AFMADDS: return FPOP3S(0, 0, 0);
+ case AFNMADDS: return FPOP3S(0, 0, 1);
+ case AFMADDD: return FPOP3S(1, 0, 0);
+ case AFNMADDD: return FPOP3S(1, 0, 1);
+ case AFMSUBS: return FPOP3S(0, 1, 0);
+ case AFNMSUBS: return FPOP3S(0, 1, 1);
+ case AFMSUBD: return FPOP3S(1, 1, 0);
+ case AFNMSUBD: return FPOP3S(1, 1, 1);
case AFCMPS: return FPCMP(0, 0, 0, 0, 0);
case AFCMPD: return FPCMP(0, 0, 1, 0, 0);
--- a/sys/src/cmd/7l/list.c
+++ b/sys/src/cmd/7l/list.c
@@ -32,15 +32,12 @@
if(p->reg == NREG && p->from3.type == D_NONE)
return fmtprint(fp, "(%ld) %A %D,%D",
p->line, a, &p->from, &p->to);
- else if(p->from.type == D_FREG)
- return fmtprint(fp, "(%ld) %A %D,F%d,%D",
- p->line, a, &p->from, p->reg, &p->to);
fmtprint(fp, "(%ld) %A %D", p->line, a, &p->from);
if(p->from3.type != D_NONE)
fmtprint(fp, ",%D", &p->from3);
if(p->reg != NREG)
- fmtprint(fp, ",R%d", p->reg);
+ fmtprint(fp, ",%c%d", p->from.type == D_FREG ? 'F' : 'R', p->reg);
fmtprint(fp, ",%D", &p->to);
return 0;
}
--- a/sys/src/cmd/7l/noop.c
+++ b/sys/src/cmd/7l/noop.c
@@ -275,6 +275,7 @@
q->line = p->line;
q->as = AB;
q->from = zprg.from;
+ q->from3 = zprg.from3;
q->to = p->to;
q->cond = p->cond;
q->link = p->link;
@@ -284,6 +285,7 @@
p->from = zprg.from;
p->from.type = D_CONST;
p->from.offset = autosize;
+ p->from3 = zprg.from3;
p->to = zprg.to;
p->to.type = D_REG;
p->to.reg = REGSP;
@@ -295,6 +297,7 @@
q->line = p->line;
q->as = AB;
q->from = zprg.from;
+ q->from3 = zprg.from3;
q->to = p->to;
q->cond = p->cond;
q->link = p->link;
@@ -305,6 +308,7 @@
p->from.type = D_XPRE;
p->from.offset = -autosize;
p->from.reg = REGSP;
+ p->from3 = zprg.from3;
p->to = zprg.to;
p->to.type = D_REG;
p->to.reg = REGLINK;
--- a/sys/src/cmd/7l/obj.c
+++ b/sys/src/cmd/7l/obj.c
@@ -555,6 +555,7 @@
{
p->as = ANOP;
p->from.type = D_NONE;
+ p->from3.type = D_NONE;
p->to.type = D_NONE;
}
@@ -1340,6 +1341,7 @@
*/
p->as = ABL;
p->from = zprg.from;
+ p->from3 = zprg.from3;
p->to = zprg.to;
p->to.type = D_BRANCH;
p->cond = ps4;
--- a/sys/src/cmd/7l/optab.c
+++ b/sys/src/cmd/7l/optab.c
@@ -417,6 +417,9 @@
{ AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 8, 0, LTO },
{ AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 8, 0, LFROM },
+ { AFMADDD, C_FREG, C_FREG, C_FREG, 70, 4, 0 },
+ { AFMADDD, C_FREG, C_NONE, C_FREG, 70, 4, 0 },
+
{ AFADDS, C_FREG, C_NONE, C_FREG, 54, 4, 0 },
{ AFADDS, C_FREG, C_REG, C_FREG, 54, 4, 0 },
{ AFADDS, C_FCON, C_NONE, C_FREG, 54, 4, 0 },
--- a/sys/src/cmd/7l/span.c
+++ b/sys/src/cmd/7l/span.c
@@ -700,6 +700,14 @@
asregclass(ushort as)
{
switch(as){
+ case AFMADDD:
+ case AFMADDS:
+ case AFMSUBD:
+ case AFMSUBS:
+ case AFNMADDS:
+ case AFNMADDD:
+ case AFNMSUBS:
+ case AFNMSUBD:
case AMOVPS:
case AMOVPD:
case AMOVPQ: return C_FREG;
@@ -1098,6 +1106,15 @@
oprange[ASMSUBL] = t;
oprange[AUMADDL] = t;
oprange[AUMSUBL] = t;
+ break;
+ case AFMADDD:
+ oprange[AFMADDS] = t;
+ oprange[AFMSUBD] = t;
+ oprange[AFMSUBS] = t;
+ oprange[AFNMADDS] = t;
+ oprange[AFNMADDD] = t;
+ oprange[AFNMSUBD] = t;
+ oprange[AFNMSUBS] = t;
break;
case AREM:
oprange[AREMW] = t;