diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index feb507db86..361b7a45c0 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -163,6 +163,12 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8 MOVB (R29)(R30<<0), R14 // ae7bbe38 MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38 MOVB R4, (R2)(R6.SXTX) // 44e82638 + FMOVS $(4.0), F0 // 0010221e + FMOVD $(4.0), F0 // 0010621e + FMOVS $(0.265625), F1 // 01302a1e + FMOVD $(0.1796875), F2 // 02f0681e + FMOVS $(0.96875), F3 // 03f02d1e + FMOVD $(28.0), F4 // 0490671e FMOVS (R2)(R6), F4 // FMOVS (R2)(R6*1), F4 // 446866bc FMOVS (R2)(R6<<2), F4 // 447866bc @@ -479,14 +485,14 @@ again: // { // outcode($1, &$2, NREG, &$4); // } - FADDD $0.5, F1 // FADDD $(0.5), F1 +// FADDD $0.5, F1 // FADDD $(0.5), F1 FADDD F1, F2 // LTYPEK frcon ',' freg ',' freg // { // outcode($1, &$2, $4.reg, &$6); // } - FADDD $0.7, F1, F2 // FADDD $(0.69999999999999996), F1, F2 +// FADDD $0.7, F1, F2 // FADDD $(0.69999999999999996), F1, F2 FADDD F1, F2, F3 // diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 00232ccd55..7507976257 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -219,8 +219,6 @@ var optab = []Optab{ {AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, {AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, - {AFADDS, C_FCON, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, - {AFADDS, C_FCON, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, {AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0}, {AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0}, {AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0}, @@ -340,9 +338,9 @@ var optab = []Optab{ {AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0}, {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0}, {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0}, - {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, + {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0}, {AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, - {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, + {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0}, {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0}, {AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0}, {AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0}, @@ -2461,6 +2459,9 @@ func buildop(ctxt *obj.Link) { } } +// chipfloat7() checks if the immediate constants available in FMOVS/FMOVD instructions. +// For details of the range of constants available, see +// http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html. func (c *ctxt7) chipfloat7(e float64) int { ei := math.Float64bits(e) l := uint32(int32(ei)) @@ -3486,19 +3487,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { case 54: /* floating point arith */ o1 = c.oprrr(p, p.As) - - var rf int - if p.From.Type == obj.TYPE_CONST { - rf = c.chipfloat7(p.From.Val.(float64)) - if rf < 0 || true { - c.ctxt.Diag("invalid floating-point immediate\n%v", p) - rf = 0 - } - - rf |= (1 << 3) - } else { - rf = int(p.From.Reg) - } + rf := int(p.From.Reg) rt := int(p.To.Reg) r := int(p.Reg) if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */ @@ -3509,6 +3498,18 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { } o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) + case 55: /* floating-point constant */ + var rf int + o1 = 0xf<<25 | 1<<21 | 1<<12 + rf = c.chipfloat7(p.From.Val.(float64)) + if rf < 0 { + c.ctxt.Diag("invalid floating-point immediate\n%v", p) + } + if p.As == AFMOVD { + o1 |= 1 << 22 + } + o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31) + case 56: /* floating point compare */ o1 = c.oprrr(p, p.As) diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index 97b8f70c9b..4476dad071 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -254,7 +254,11 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { switch p.As { case AFMOVS: if p.From.Type == obj.TYPE_FCONST { - f32 := float32(p.From.Val.(float64)) + f64 := p.From.Val.(float64) + f32 := float32(f64) + if c.chipfloat7(f64) > 0 { + break + } if math.Float32bits(f32) == 0 { p.From.Type = obj.TYPE_REG p.From.Reg = REGZERO @@ -269,6 +273,9 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { case AFMOVD: if p.From.Type == obj.TYPE_FCONST { f64 := p.From.Val.(float64) + if c.chipfloat7(f64) > 0 { + break + } if math.Float64bits(f64) == 0 { p.From.Type = obj.TYPE_REG p.From.Reg = REGZERO