2015-09-05 20:27:00 -04:00
|
|
|
// cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
|
|
|
|
|
//
|
|
|
|
|
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
|
|
|
|
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
|
|
|
|
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
|
|
|
|
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
|
|
|
|
|
// Portions Copyright © 2004,2006 Bruce Ellis
|
|
|
|
|
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
|
|
|
|
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
|
2016-04-10 14:32:26 -07:00
|
|
|
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
2015-09-05 20:27:00 -04:00
|
|
|
//
|
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
|
//
|
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
|
//
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
// THE SOFTWARE.
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
package mips
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"cmd/internal/obj"
|
2017-04-18 12:53:25 -07:00
|
|
|
"cmd/internal/objabi"
|
2017-03-21 22:23:45 -07:00
|
|
|
"cmd/internal/sys"
|
2015-09-05 20:27:00 -04:00
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"sort"
|
|
|
|
|
)
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
// ctxt0 holds state while assembling a single function.
|
|
|
|
|
// Each function gets a fresh ctxt0.
|
|
|
|
|
// This allows for multiple functions to be safely concurrently assembled.
|
|
|
|
|
type ctxt0 struct {
|
|
|
|
|
ctxt *obj.Link
|
|
|
|
|
newprog obj.ProgAlloc
|
|
|
|
|
cursym *obj.LSym
|
|
|
|
|
autosize int32
|
|
|
|
|
instoffset int64
|
|
|
|
|
pc int64
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-05 20:27:00 -04:00
|
|
|
// Instruction layout.
|
|
|
|
|
|
|
|
|
|
const (
|
2016-10-18 23:50:37 +02:00
|
|
|
mips64FuncAlign = 8
|
2015-09-05 20:27:00 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
r0iszero = 1
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Optab struct {
|
2017-03-21 22:23:45 -07:00
|
|
|
as obj.As
|
|
|
|
|
a1 uint8
|
|
|
|
|
a2 uint8
|
|
|
|
|
a3 uint8
|
|
|
|
|
type_ int8
|
|
|
|
|
size int8
|
|
|
|
|
param int16
|
2017-03-23 10:56:58 +11:00
|
|
|
family sys.ArchFamily // 0 means both sys.MIPS and sys.MIPS64
|
2019-10-28 14:41:49 -04:00
|
|
|
flag uint8
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2019-10-26 22:49:13 -04:00
|
|
|
const (
|
|
|
|
|
// Optab.flag
|
|
|
|
|
NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
|
|
|
|
|
)
|
|
|
|
|
|
2015-09-05 20:27:00 -04:00
|
|
|
var optab = []Optab{
|
2019-10-28 14:41:49 -04:00
|
|
|
{obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0, sys.MIPS64, 0},
|
|
|
|
|
{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0, sys.MIPS64, 0},
|
2019-10-26 22:49:13 -04:00
|
|
|
{AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0, 0, NOTUSETMP},
|
2019-10-28 14:41:49 -04:00
|
|
|
{AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0, 0, 0},
|
2019-10-26 22:49:13 -04:00
|
|
|
{AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0, sys.MIPS64, NOTUSETMP},
|
2019-10-28 14:41:49 -04:00
|
|
|
|
|
|
|
|
{ASUB, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
|
|
|
|
|
{ASUBV, C_REG, C_REG, C_REG, 2, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AADD, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
|
|
|
|
|
{AADDV, C_REG, C_REG, C_REG, 2, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AAND, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
|
|
|
|
|
{ASUB, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
|
|
|
|
|
{ASUBV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AADD, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
|
|
|
|
|
{AADDV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AAND, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
|
|
|
|
|
{ACMOVN, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
|
|
|
|
|
{ANEGW, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
|
|
|
|
|
{ANEGV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
|
|
|
|
|
{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
|
|
|
|
|
{ASLLV, C_REG, C_NONE, C_REG, 9, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{ASLLV, C_REG, C_REG, C_REG, 9, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{ACLO, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0, 0, 0},
|
|
|
|
|
{AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0, 0, 0},
|
|
|
|
|
{ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0, 0, 0},
|
|
|
|
|
{AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
|
|
|
|
|
{AMOVVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVVL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVVL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVVL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{ASC, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
|
|
|
|
|
{ASCV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVVL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVVL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVVL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{ALL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
|
|
|
|
|
{ALLV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVWU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVWU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
|
|
|
|
|
{ASC, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
|
2019-10-26 22:49:13 -04:00
|
|
|
{AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
|
|
|
|
|
{AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0, sys.MIPS64, NOTUSETMP},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0, sys.MIPS64, NOTUSETMP},
|
|
|
|
|
{AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
|
|
|
|
|
{AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
|
2019-10-28 14:41:49 -04:00
|
|
|
|
|
|
|
|
{AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVBU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVW, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVWU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVBU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVW, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVB, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
|
2019-10-26 22:49:13 -04:00
|
|
|
{AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
|
|
|
|
|
{AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0, sys.MIPS64, NOTUSETMP},
|
|
|
|
|
{AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0, sys.MIPS64, NOTUSETMP},
|
|
|
|
|
{AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
|
|
|
|
|
{AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
|
2019-10-28 14:41:49 -04:00
|
|
|
|
|
|
|
|
{AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP, sys.MIPS64, 0},
|
2019-10-26 22:49:13 -04:00
|
|
|
{AMOVW, C_LECON, C_NONE, C_REG, 52, 8, REGSB, sys.MIPS, NOTUSETMP},
|
|
|
|
|
{AMOVW, C_LECON, C_NONE, C_REG, 52, 12, REGSB, sys.MIPS64, NOTUSETMP},
|
|
|
|
|
{AMOVV, C_LECON, C_NONE, C_REG, 52, 12, REGSB, sys.MIPS64, NOTUSETMP},
|
2019-10-28 14:41:49 -04:00
|
|
|
|
|
|
|
|
{AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, sys.MIPS64, 0},
|
2019-10-26 22:49:13 -04:00
|
|
|
{AMOVW, C_STCON, C_NONE, C_REG, 55, 8, 0, 0, NOTUSETMP},
|
|
|
|
|
{AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0, sys.MIPS64, NOTUSETMP},
|
2019-10-28 14:41:49 -04:00
|
|
|
|
|
|
|
|
{AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0, sys.MIPS64, 0},
|
2019-10-26 22:49:13 -04:00
|
|
|
{AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0, 0, NOTUSETMP},
|
|
|
|
|
{AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0, sys.MIPS64, NOTUSETMP},
|
2019-10-28 14:41:49 -04:00
|
|
|
|
|
|
|
|
{AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AMUL, C_REG, C_REG, C_NONE, 22, 4, 0, 0, 0},
|
|
|
|
|
{AMUL, C_REG, C_REG, C_REG, 22, 4, 0, 0, 0},
|
|
|
|
|
{AMULV, C_REG, C_REG, C_NONE, 22, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0, 0, 0},
|
|
|
|
|
{AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, 0, 0},
|
|
|
|
|
{AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0, 0, 0},
|
|
|
|
|
{AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AADDV, C_ADD0CON, C_REG, C_REG, 4, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AADDV, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AADDV, C_ANDCON, C_REG, C_REG, 10, 8, 0, sys.MIPS64, 0},
|
|
|
|
|
{AADDV, C_ANDCON, C_NONE, C_REG, 10, 8, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0, 0, 0},
|
|
|
|
|
{AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0, 0, 0},
|
|
|
|
|
{AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0, 0, 0},
|
|
|
|
|
{AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AADD, C_UCON, C_REG, C_REG, 25, 8, 0, 0, 0},
|
|
|
|
|
{AADD, C_UCON, C_NONE, C_REG, 25, 8, 0, 0, 0},
|
|
|
|
|
{AADDV, C_UCON, C_REG, C_REG, 25, 8, 0, sys.MIPS64, 0},
|
|
|
|
|
{AADDV, C_UCON, C_NONE, C_REG, 25, 8, 0, sys.MIPS64, 0},
|
|
|
|
|
{AAND, C_UCON, C_REG, C_REG, 25, 8, 0, 0, 0},
|
|
|
|
|
{AAND, C_UCON, C_NONE, C_REG, 25, 8, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AADD, C_LCON, C_NONE, C_REG, 23, 12, 0, 0, 0},
|
|
|
|
|
{AADDV, C_LCON, C_NONE, C_REG, 23, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AAND, C_LCON, C_NONE, C_REG, 23, 12, 0, 0, 0},
|
|
|
|
|
{AADD, C_LCON, C_REG, C_REG, 23, 12, 0, 0, 0},
|
|
|
|
|
{AADDV, C_LCON, C_REG, C_REG, 23, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AAND, C_LCON, C_REG, C_REG, 23, 12, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{ASLL, C_SCON, C_REG, C_REG, 16, 4, 0, 0, 0},
|
|
|
|
|
{ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{ASLLV, C_SCON, C_REG, C_REG, 16, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{ASLLV, C_SCON, C_NONE, C_REG, 16, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0, 0, 0},
|
|
|
|
|
{ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0, 0},
|
|
|
|
|
{ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0, 0},
|
2019-10-26 22:49:13 -04:00
|
|
|
{ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0, 0, NOTUSETMP},
|
2019-10-28 14:41:49 -04:00
|
|
|
|
|
|
|
|
{AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0},
|
|
|
|
|
{AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO, 0, 0},
|
|
|
|
|
{AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVD, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVW, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVD, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVF, C_ADDR, C_NONE, C_FREG, 51, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVD, C_ADDR, C_NONE, C_FREG, 51, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0, 0},
|
|
|
|
|
{AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0, 0},
|
|
|
|
|
{AMOVW, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
|
|
|
|
|
{AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0, 0, 0},
|
|
|
|
|
{AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{AMOVW, C_REG, C_NONE, C_FCREG, 41, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_REG, C_NONE, C_FCREG, 41, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0, 0, 0},
|
|
|
|
|
{AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
|
|
|
|
|
{ATEQ, C_SCON, C_REG, C_REG, 15, 4, 0, 0, 0},
|
|
|
|
|
{ATEQ, C_SCON, C_NONE, C_REG, 15, 4, 0, 0, 0},
|
|
|
|
|
{ACMOVT, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0},
|
|
|
|
|
|
cmd/asm: add MIPS MSA LD/ST/LDI support for mips64x
This CL adding primitive asm support of MIPS MSA by introducing
new sets of register W0-W31 (C_WREG) and 12 new instructions:
* VMOV{B,H,W,D} ADDCONST, WREG (Vector load immediate)
* VMOV{B,H,W,D} SOREG, WREG (Vector load)
* VMOV{B,H,W,D} WREG, SOREG (Vector store)
Ref: MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module
Change-Id: I3362c59a73c82c94769c18a19a0bee7e5029217d
Reviewed-on: https://go-review.googlesource.com/c/go/+/215723
Run-TryBot: Meng Zhuo <mengzhuo1203@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-03-03 23:05:32 +08:00
|
|
|
{AVMOVB, C_SCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AVMOVB, C_ADDCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AVMOVB, C_SOREG, C_NONE, C_WREG, 57, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
{AVMOVB, C_WREG, C_NONE, C_SOREG, 58, 4, 0, sys.MIPS64, 0},
|
|
|
|
|
|
2019-10-28 14:41:49 -04:00
|
|
|
{ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0}, /* really CACHE instruction */
|
|
|
|
|
{ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
|
|
|
|
|
{ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
|
|
|
|
|
{ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0, 0},
|
|
|
|
|
|
|
|
|
|
{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0, 0},
|
|
|
|
|
{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
|
|
|
|
|
{obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
|
|
|
|
|
{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
|
|
|
|
|
{obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0}, // same as AJMP
|
|
|
|
|
{obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0}, // same as AJMP
|
|
|
|
|
|
|
|
|
|
{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2016-03-07 20:30:38 -08:00
|
|
|
var oprange [ALAST & obj.AMask][]Optab
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2016-03-07 20:30:38 -08:00
|
|
|
var xcmp [C_NCLASS][C_NCLASS]bool
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2017-04-04 14:31:55 -07:00
|
|
|
func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
2020-01-17 13:54:30 -05:00
|
|
|
if ctxt.Retpoline {
|
|
|
|
|
ctxt.Diag("-spectre=ret not supported on mips")
|
|
|
|
|
ctxt.Retpoline = false // don't keep printing
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 10:18:34 -07:00
|
|
|
p := cursym.Func.Text
|
2015-09-05 20:27:00 -04:00
|
|
|
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
|
|
|
|
|
c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset + ctxt.FixedFrameSize())}
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2016-03-07 20:30:38 -08:00
|
|
|
if oprange[AOR&obj.AMask] == nil {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("mips ops not initialized, call mips.buildop first")
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 07:31:23 -07:00
|
|
|
pc := int64(0)
|
|
|
|
|
p.Pc = pc
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
var m int
|
|
|
|
|
var o *Optab
|
|
|
|
|
for p = p.Link; p != nil; p = p.Link {
|
2017-04-10 07:31:23 -07:00
|
|
|
p.Pc = pc
|
2017-04-10 14:15:57 -07:00
|
|
|
o = c.oplook(p)
|
2015-09-05 20:27:00 -04:00
|
|
|
m = int(o.size)
|
|
|
|
|
if m == 0 {
|
2017-03-03 14:27:24 -08:00
|
|
|
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("zero-width instruction\n%v", p)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 07:31:23 -07:00
|
|
|
pc += int64(m)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
c.cursym.Size = pc
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* if any procedure is large enough to
|
|
|
|
|
* generate a large SBRA branch, then
|
|
|
|
|
* generate extra passes putting branches
|
|
|
|
|
* around jmps to fix. this is rare.
|
|
|
|
|
*/
|
|
|
|
|
bflag := 1
|
|
|
|
|
|
|
|
|
|
var otxt int64
|
|
|
|
|
var q *obj.Prog
|
|
|
|
|
for bflag != 0 {
|
|
|
|
|
bflag = 0
|
2017-04-10 07:31:23 -07:00
|
|
|
pc = 0
|
2017-04-18 10:18:34 -07:00
|
|
|
for p = c.cursym.Func.Text.Link; p != nil; p = p.Link {
|
2017-04-10 07:31:23 -07:00
|
|
|
p.Pc = pc
|
2017-04-10 14:15:57 -07:00
|
|
|
o = c.oplook(p)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
// very large conditional branches
|
2015-09-10 11:13:00 -04:00
|
|
|
if o.type_ == 6 && p.Pcond != nil {
|
2017-04-10 07:31:23 -07:00
|
|
|
otxt = p.Pcond.Pc - pc
|
2015-09-10 11:13:00 -04:00
|
|
|
if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
|
2017-04-10 14:15:57 -07:00
|
|
|
q = c.newprog()
|
2015-09-05 20:27:00 -04:00
|
|
|
q.Link = p.Link
|
|
|
|
|
p.Link = q
|
2015-09-10 11:13:00 -04:00
|
|
|
q.As = AJMP
|
2016-12-09 14:30:40 -05:00
|
|
|
q.Pos = p.Pos
|
2015-09-05 20:27:00 -04:00
|
|
|
q.To.Type = obj.TYPE_BRANCH
|
|
|
|
|
q.Pcond = p.Pcond
|
|
|
|
|
p.Pcond = q
|
2017-04-10 14:15:57 -07:00
|
|
|
q = c.newprog()
|
2015-09-05 20:27:00 -04:00
|
|
|
q.Link = p.Link
|
|
|
|
|
p.Link = q
|
2015-09-10 11:13:00 -04:00
|
|
|
q.As = AJMP
|
2016-12-09 14:30:40 -05:00
|
|
|
q.Pos = p.Pos
|
2015-09-05 20:27:00 -04:00
|
|
|
q.To.Type = obj.TYPE_BRANCH
|
|
|
|
|
q.Pcond = q.Link.Link
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
c.addnop(p.Link)
|
|
|
|
|
c.addnop(p)
|
2015-09-05 20:27:00 -04:00
|
|
|
bflag = 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m = int(o.size)
|
|
|
|
|
if m == 0 {
|
2017-03-03 14:27:24 -08:00
|
|
|
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("zero-width instruction\n%v", p)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 07:31:23 -07:00
|
|
|
pc += int64(m)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
c.cursym.Size = pc
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.ctxt.Arch.Family == sys.MIPS64 {
|
2017-04-10 07:31:23 -07:00
|
|
|
pc += -pc & (mips64FuncAlign - 1)
|
2016-10-18 23:50:37 +02:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
c.cursym.Size = pc
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* lay out the code, emitting code and data relocations.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
c.cursym.Grow(c.cursym.Size)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
bp := c.cursym.P
|
2015-09-05 20:27:00 -04:00
|
|
|
var i int32
|
2015-09-10 11:13:00 -04:00
|
|
|
var out [4]uint32
|
2017-04-18 10:18:34 -07:00
|
|
|
for p := c.cursym.Func.Text.Link; p != nil; p = p.Link {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.pc = p.Pc
|
|
|
|
|
o = c.oplook(p)
|
2015-09-05 20:27:00 -04:00
|
|
|
if int(o.size) > 4*len(out) {
|
2015-09-10 11:13:00 -04:00
|
|
|
log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
c.asmout(p, o, out[:])
|
2015-09-05 20:27:00 -04:00
|
|
|
for i = 0; i < int32(o.size/4); i++ {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
|
2015-09-05 20:27:00 -04:00
|
|
|
bp = bp[4:]
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-10-26 22:49:13 -04:00
|
|
|
|
|
|
|
|
// Mark nonpreemptible instruction sequences.
|
|
|
|
|
// We use REGTMP as a scratch register during call injection,
|
|
|
|
|
// so instruction sequences that use REGTMP are unsafe to
|
|
|
|
|
// preempt asynchronously.
|
cmd/internal/obj, runtime: preempt & restart some instruction sequences
On some architectures, for async preemption the injected call
needs to clobber a register (usually REGTMP) in order to return
to the preempted function. As a consequence, the PC ranges where
REGTMP is live are not preemptible.
The uses of REGTMP are usually generated by the assembler, where
it needs to load or materialize a large constant or offset that
doesn't fit into the instruction. In those cases, REGTMP is not
live at the start of the instruction sequence. Instead of giving
up preemption in those cases, we could preempt it and restart the
sequence when resuming the execution. Basically, this is like
reissuing an interrupted instruction, except that here the
"instruction" is a Prog that consists of multiple machine
instructions. For this to work, we need to generate PC data to
mark the start of the Prog.
Currently this is only done for ARM64.
TODO: the split-stack function prologue is currently not async
preemptible. We could use this mechanism, preempt it and restart
at the function entry.
Change-Id: I37cb282f8e606e7ab6f67b3edfdc6063097b4bd1
Reviewed-on: https://go-review.googlesource.com/c/go/+/208126
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2019-11-20 17:10:34 -05:00
|
|
|
obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, nil)
|
2019-10-26 22:49:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return whether p is an unsafe point.
|
|
|
|
|
func (c *ctxt0) isUnsafePoint(p *obj.Prog) bool {
|
|
|
|
|
if p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
// Most of the multi-instruction sequence uses REGTMP, except
|
|
|
|
|
// ones marked safe.
|
|
|
|
|
o := c.oplook(p)
|
|
|
|
|
return o.size > 4 && o.flag&NOTUSETMP == 0
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isint32(v int64) bool {
|
|
|
|
|
return int64(int32(v)) == v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isuint32(v uint64) bool {
|
|
|
|
|
return uint64(uint32(v)) == v
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
func (c *ctxt0) aclass(a *obj.Addr) int {
|
2015-09-05 20:27:00 -04:00
|
|
|
switch a.Type {
|
|
|
|
|
case obj.TYPE_NONE:
|
|
|
|
|
return C_NONE
|
|
|
|
|
|
|
|
|
|
case obj.TYPE_REG:
|
|
|
|
|
if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
|
|
|
|
|
return C_REG
|
|
|
|
|
}
|
|
|
|
|
if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
|
|
|
|
|
return C_FREG
|
|
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
if REG_M0 <= a.Reg && a.Reg <= REG_M31 {
|
|
|
|
|
return C_MREG
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
|
|
|
|
|
return C_FCREG
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
cmd/asm: add MIPS MSA LD/ST/LDI support for mips64x
This CL adding primitive asm support of MIPS MSA by introducing
new sets of register W0-W31 (C_WREG) and 12 new instructions:
* VMOV{B,H,W,D} ADDCONST, WREG (Vector load immediate)
* VMOV{B,H,W,D} SOREG, WREG (Vector load)
* VMOV{B,H,W,D} WREG, SOREG (Vector store)
Ref: MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module
Change-Id: I3362c59a73c82c94769c18a19a0bee7e5029217d
Reviewed-on: https://go-review.googlesource.com/c/go/+/215723
Run-TryBot: Meng Zhuo <mengzhuo1203@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-03-03 23:05:32 +08:00
|
|
|
if REG_W0 <= a.Reg && a.Reg <= REG_W31 {
|
|
|
|
|
return C_WREG
|
|
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
if a.Reg == REG_LO {
|
|
|
|
|
return C_LO
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
if a.Reg == REG_HI {
|
|
|
|
|
return C_HI
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
return C_GOK
|
|
|
|
|
|
|
|
|
|
case obj.TYPE_MEM:
|
|
|
|
|
switch a.Name {
|
|
|
|
|
case obj.NAME_EXTERN,
|
|
|
|
|
obj.NAME_STATIC:
|
|
|
|
|
if a.Sym == nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
c.instoffset = a.Offset
|
2015-09-05 20:27:00 -04:00
|
|
|
if a.Sym != nil { // use relocation
|
2017-04-18 12:53:25 -07:00
|
|
|
if a.Sym.Type == objabi.STLSBSS {
|
2016-04-27 22:18:14 -04:00
|
|
|
return C_TLS
|
|
|
|
|
}
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_ADDR
|
|
|
|
|
}
|
|
|
|
|
return C_LEXT
|
|
|
|
|
|
|
|
|
|
case obj.NAME_AUTO:
|
2017-07-18 08:35:00 -04:00
|
|
|
if a.Reg == REGSP {
|
|
|
|
|
// unset base register for better printing, since
|
|
|
|
|
// a.Offset is still relative to pseudo-SP.
|
|
|
|
|
a.Reg = obj.REG_NONE
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
c.instoffset = int64(c.autosize) + a.Offset
|
|
|
|
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_SAUTO
|
|
|
|
|
}
|
|
|
|
|
return C_LAUTO
|
|
|
|
|
|
|
|
|
|
case obj.NAME_PARAM:
|
2017-07-18 08:35:00 -04:00
|
|
|
if a.Reg == REGSP {
|
|
|
|
|
// unset base register for better printing, since
|
|
|
|
|
// a.Offset is still relative to pseudo-FP.
|
|
|
|
|
a.Reg = obj.REG_NONE
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
|
|
|
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_SAUTO
|
|
|
|
|
}
|
|
|
|
|
return C_LAUTO
|
|
|
|
|
|
|
|
|
|
case obj.NAME_NONE:
|
2017-04-10 14:15:57 -07:00
|
|
|
c.instoffset = a.Offset
|
|
|
|
|
if c.instoffset == 0 {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_ZOREG
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_SOREG
|
|
|
|
|
}
|
|
|
|
|
return C_LOREG
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return C_GOK
|
|
|
|
|
|
|
|
|
|
case obj.TYPE_TEXTSIZE:
|
|
|
|
|
return C_TEXTSIZE
|
|
|
|
|
|
|
|
|
|
case obj.TYPE_CONST,
|
|
|
|
|
obj.TYPE_ADDR:
|
|
|
|
|
switch a.Name {
|
2015-09-10 11:13:00 -04:00
|
|
|
case obj.NAME_NONE:
|
2017-04-10 14:15:57 -07:00
|
|
|
c.instoffset = a.Offset
|
2015-09-05 20:27:00 -04:00
|
|
|
if a.Reg != 0 {
|
2017-04-10 14:15:57 -07:00
|
|
|
if -BIG <= c.instoffset && c.instoffset <= BIG {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_SACON
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if isint32(c.instoffset) {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_LACON
|
|
|
|
|
}
|
|
|
|
|
return C_DACON
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case obj.NAME_EXTERN,
|
|
|
|
|
obj.NAME_STATIC:
|
|
|
|
|
s := a.Sym
|
|
|
|
|
if s == nil {
|
2018-04-29 22:17:23 +09:00
|
|
|
return C_GOK
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
c.instoffset = a.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
if s.Type == objabi.STLSBSS {
|
2016-04-27 22:18:14 -04:00
|
|
|
return C_STCON // address of TLS variable
|
|
|
|
|
}
|
2016-04-27 22:18:02 -04:00
|
|
|
return C_LECON
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
case obj.NAME_AUTO:
|
2017-07-18 08:35:00 -04:00
|
|
|
if a.Reg == REGSP {
|
|
|
|
|
// unset base register for better printing, since
|
|
|
|
|
// a.Offset is still relative to pseudo-SP.
|
|
|
|
|
a.Reg = obj.REG_NONE
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
c.instoffset = int64(c.autosize) + a.Offset
|
|
|
|
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_SACON
|
|
|
|
|
}
|
|
|
|
|
return C_LACON
|
|
|
|
|
|
|
|
|
|
case obj.NAME_PARAM:
|
2017-07-18 08:35:00 -04:00
|
|
|
if a.Reg == REGSP {
|
|
|
|
|
// unset base register for better printing, since
|
|
|
|
|
// a.Offset is still relative to pseudo-FP.
|
|
|
|
|
a.Reg = obj.REG_NONE
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
|
|
|
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_SACON
|
|
|
|
|
}
|
|
|
|
|
return C_LACON
|
|
|
|
|
|
2018-04-29 22:17:23 +09:00
|
|
|
default:
|
|
|
|
|
return C_GOK
|
|
|
|
|
}
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.instoffset >= 0 {
|
|
|
|
|
if c.instoffset == 0 {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_ZCON
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.instoffset <= 0x7fff {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_SCON
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.instoffset <= 0xffff {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_ANDCON
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.instoffset&0xffff == 0 && isuint32(uint64(c.instoffset)) { /* && (instoffset & (1<<31)) == 0) */
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_UCON
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_LCON
|
|
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
return C_LCON // C_DCON
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.instoffset >= -0x8000 {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_ADDCON
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.instoffset&0xffff == 0 && isint32(c.instoffset) {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_UCON
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
if isint32(c.instoffset) {
|
2015-09-05 20:27:00 -04:00
|
|
|
return C_LCON
|
|
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
return C_LCON // C_DCON
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
case obj.TYPE_BRANCH:
|
|
|
|
|
return C_SBRA
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return C_GOK
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func prasm(p *obj.Prog) {
|
|
|
|
|
fmt.Printf("%v\n", p)
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
func (c *ctxt0) oplook(p *obj.Prog) *Optab {
|
2016-03-07 20:30:38 -08:00
|
|
|
if oprange[AOR&obj.AMask] == nil {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("mips ops not initialized, call mips.buildop first")
|
2015-09-10 11:13:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-05 20:27:00 -04:00
|
|
|
a1 := int(p.Optab)
|
|
|
|
|
if a1 != 0 {
|
2016-04-12 12:16:20 -07:00
|
|
|
return &optab[a1-1]
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
a1 = int(p.From.Class)
|
|
|
|
|
if a1 == 0 {
|
2017-04-10 14:15:57 -07:00
|
|
|
a1 = c.aclass(&p.From) + 1
|
2015-09-05 20:27:00 -04:00
|
|
|
p.From.Class = int8(a1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a1--
|
2015-09-10 11:13:00 -04:00
|
|
|
a3 := int(p.To.Class)
|
|
|
|
|
if a3 == 0 {
|
2017-04-10 14:15:57 -07:00
|
|
|
a3 = c.aclass(&p.To) + 1
|
2015-09-10 11:13:00 -04:00
|
|
|
p.To.Class = int8(a3)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a3--
|
|
|
|
|
a2 := C_NONE
|
|
|
|
|
if p.Reg != 0 {
|
|
|
|
|
a2 = C_REG
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 20:30:38 -08:00
|
|
|
ops := oprange[p.As&obj.AMask]
|
|
|
|
|
c1 := &xcmp[a1]
|
|
|
|
|
c3 := &xcmp[a3]
|
|
|
|
|
for i := range ops {
|
|
|
|
|
op := &ops[i]
|
2017-04-10 14:15:57 -07:00
|
|
|
if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] && (op.family == 0 || c.ctxt.Arch.Family == op.family) {
|
2016-03-07 20:30:38 -08:00
|
|
|
p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
|
|
|
|
|
return op
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("illegal combination %v %v %v %v", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
|
2015-09-05 20:27:00 -04:00
|
|
|
prasm(p)
|
2018-01-25 11:46:06 -05:00
|
|
|
// Turn illegal instruction into an UNDEF, avoid crashing in asmout.
|
2019-10-28 14:41:49 -04:00
|
|
|
return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0, 0}
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func cmp(a int, b int) bool {
|
|
|
|
|
if a == b {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
switch a {
|
|
|
|
|
case C_LCON:
|
|
|
|
|
if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case C_ADD0CON:
|
|
|
|
|
if b == C_ADDCON {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
2015-09-05 20:27:00 -04:00
|
|
|
case C_ADDCON:
|
|
|
|
|
if b == C_ZCON || b == C_SCON {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case C_AND0CON:
|
|
|
|
|
if b == C_ANDCON {
|
2015-09-05 20:27:00 -04:00
|
|
|
return true
|
|
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
fallthrough
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case C_ANDCON:
|
|
|
|
|
if b == C_ZCON || b == C_SCON {
|
2015-09-05 20:27:00 -04:00
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_UCON:
|
|
|
|
|
if b == C_ZCON {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_SCON:
|
|
|
|
|
if b == C_ZCON {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_LACON:
|
|
|
|
|
if b == C_SACON {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_LBRA:
|
|
|
|
|
if b == C_SBRA {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_LEXT:
|
|
|
|
|
if b == C_SEXT {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_LAUTO:
|
|
|
|
|
if b == C_SAUTO {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_REG:
|
|
|
|
|
if b == C_ZCON {
|
|
|
|
|
return r0iszero != 0 /*TypeKind(100016)*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_LOREG:
|
|
|
|
|
if b == C_ZOREG || b == C_SOREG {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case C_SOREG:
|
|
|
|
|
if b == C_ZOREG {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ocmp []Optab
|
|
|
|
|
|
|
|
|
|
func (x ocmp) Len() int {
|
|
|
|
|
return len(x)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (x ocmp) Swap(i, j int) {
|
|
|
|
|
x[i], x[j] = x[j], x[i]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (x ocmp) Less(i, j int) bool {
|
|
|
|
|
p1 := &x[i]
|
|
|
|
|
p2 := &x[j]
|
|
|
|
|
n := int(p1.as) - int(p2.as)
|
|
|
|
|
if n != 0 {
|
|
|
|
|
return n < 0
|
|
|
|
|
}
|
|
|
|
|
n = int(p1.a1) - int(p2.a1)
|
|
|
|
|
if n != 0 {
|
|
|
|
|
return n < 0
|
|
|
|
|
}
|
|
|
|
|
n = int(p1.a2) - int(p2.a2)
|
|
|
|
|
if n != 0 {
|
|
|
|
|
return n < 0
|
|
|
|
|
}
|
|
|
|
|
n = int(p1.a3) - int(p2.a3)
|
|
|
|
|
if n != 0 {
|
|
|
|
|
return n < 0
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
2016-04-27 22:18:02 -04:00
|
|
|
|
2016-03-07 18:00:08 -08:00
|
|
|
func opset(a, b0 obj.As) {
|
2015-09-05 20:27:00 -04:00
|
|
|
oprange[a&obj.AMask] = oprange[b0]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func buildop(ctxt *obj.Link) {
|
2017-04-06 13:42:31 -07:00
|
|
|
if oprange[AOR&obj.AMask] != nil {
|
|
|
|
|
// Already initialized; stop now.
|
|
|
|
|
// This happens in the cmd/asm tests,
|
|
|
|
|
// each of which re-initializes the arch.
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-05 20:27:00 -04:00
|
|
|
var n int
|
|
|
|
|
|
|
|
|
|
for i := 0; i < C_NCLASS; i++ {
|
|
|
|
|
for n = 0; n < C_NCLASS; n++ {
|
|
|
|
|
if cmp(n, i) {
|
2016-03-07 20:30:38 -08:00
|
|
|
xcmp[i][n] = true
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for n = 0; optab[n].as != obj.AXXX; n++ {
|
|
|
|
|
}
|
|
|
|
|
sort.Sort(ocmp(optab[:n]))
|
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
|
r := optab[i].as
|
|
|
|
|
r0 := r & obj.AMask
|
2016-03-07 20:30:38 -08:00
|
|
|
start := i
|
2015-09-05 20:27:00 -04:00
|
|
|
for optab[i].as == r {
|
|
|
|
|
i++
|
|
|
|
|
}
|
2016-03-07 20:30:38 -08:00
|
|
|
oprange[r0] = optab[start:i]
|
2015-09-05 20:27:00 -04:00
|
|
|
i--
|
|
|
|
|
|
|
|
|
|
switch r {
|
|
|
|
|
default:
|
2016-07-18 21:59:14 -07:00
|
|
|
ctxt.Diag("unknown op in build: %v", r)
|
2017-10-10 17:43:41 -07:00
|
|
|
ctxt.DiagFlush()
|
2015-09-05 20:27:00 -04:00
|
|
|
log.Fatalf("bad code")
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case AABSF:
|
|
|
|
|
opset(AMOVFD, r0)
|
|
|
|
|
opset(AMOVDF, r0)
|
|
|
|
|
opset(AMOVWF, r0)
|
|
|
|
|
opset(AMOVFW, r0)
|
|
|
|
|
opset(AMOVWD, r0)
|
|
|
|
|
opset(AMOVDW, r0)
|
|
|
|
|
opset(ANEGF, r0)
|
|
|
|
|
opset(ANEGD, r0)
|
|
|
|
|
opset(AABSD, r0)
|
|
|
|
|
opset(ATRUNCDW, r0)
|
|
|
|
|
opset(ATRUNCFW, r0)
|
2016-10-18 23:50:37 +02:00
|
|
|
opset(ASQRTF, r0)
|
|
|
|
|
opset(ASQRTD, r0)
|
|
|
|
|
|
|
|
|
|
case AMOVVF:
|
2015-09-10 11:13:00 -04:00
|
|
|
opset(AMOVVD, r0)
|
2016-10-18 23:50:37 +02:00
|
|
|
opset(AMOVFV, r0)
|
2015-09-10 11:13:00 -04:00
|
|
|
opset(AMOVDV, r0)
|
2016-10-18 23:50:37 +02:00
|
|
|
opset(ATRUNCDV, r0)
|
|
|
|
|
opset(ATRUNCFV, r0)
|
2015-09-10 11:13:00 -04:00
|
|
|
|
|
|
|
|
case AADD:
|
|
|
|
|
opset(ASGT, r0)
|
|
|
|
|
opset(ASGTU, r0)
|
|
|
|
|
opset(AADDU, r0)
|
2016-10-18 23:50:37 +02:00
|
|
|
|
|
|
|
|
case AADDV:
|
2015-09-10 11:13:00 -04:00
|
|
|
opset(AADDVU, r0)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case AADDF:
|
|
|
|
|
opset(ADIVF, r0)
|
|
|
|
|
opset(ADIVD, r0)
|
|
|
|
|
opset(AMULF, r0)
|
|
|
|
|
opset(AMULD, r0)
|
|
|
|
|
opset(ASUBF, r0)
|
|
|
|
|
opset(ASUBD, r0)
|
|
|
|
|
opset(AADDD, r0)
|
|
|
|
|
|
|
|
|
|
case AAND:
|
|
|
|
|
opset(AOR, r0)
|
|
|
|
|
opset(AXOR, r0)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
case ABEQ:
|
|
|
|
|
opset(ABNE, r0)
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case ABLEZ:
|
|
|
|
|
opset(ABGEZ, r0)
|
|
|
|
|
opset(ABGEZAL, r0)
|
|
|
|
|
opset(ABLTZ, r0)
|
|
|
|
|
opset(ABLTZAL, r0)
|
|
|
|
|
opset(ABGTZ, r0)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case AMOVB:
|
|
|
|
|
opset(AMOVH, r0)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case AMOVBU:
|
|
|
|
|
opset(AMOVHU, r0)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case AMUL:
|
|
|
|
|
opset(AREM, r0)
|
|
|
|
|
opset(AREMU, r0)
|
|
|
|
|
opset(ADIVU, r0)
|
|
|
|
|
opset(AMULU, r0)
|
|
|
|
|
opset(ADIV, r0)
|
2019-03-15 08:26:53 +00:00
|
|
|
opset(AMADD, r0)
|
|
|
|
|
opset(AMSUB, r0)
|
2016-10-18 23:50:37 +02:00
|
|
|
|
|
|
|
|
case AMULV:
|
2015-09-10 11:13:00 -04:00
|
|
|
opset(ADIVV, r0)
|
|
|
|
|
opset(ADIVVU, r0)
|
|
|
|
|
opset(AMULVU, r0)
|
|
|
|
|
opset(AREMV, r0)
|
|
|
|
|
opset(AREMVU, r0)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case ASLL:
|
|
|
|
|
opset(ASRL, r0)
|
|
|
|
|
opset(ASRA, r0)
|
2016-10-18 23:50:37 +02:00
|
|
|
|
|
|
|
|
case ASLLV:
|
2015-09-10 11:13:00 -04:00
|
|
|
opset(ASRAV, r0)
|
|
|
|
|
opset(ASRLV, r0)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case ASUB:
|
|
|
|
|
opset(ASUBU, r0)
|
|
|
|
|
opset(ANOR, r0)
|
|
|
|
|
|
2016-10-18 23:50:37 +02:00
|
|
|
case ASUBV:
|
|
|
|
|
opset(ASUBVU, r0)
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case ASYSCALL:
|
2016-10-18 23:50:37 +02:00
|
|
|
opset(ASYNC, r0)
|
2017-04-11 10:39:55 -04:00
|
|
|
opset(ANOOP, r0)
|
2015-09-10 11:13:00 -04:00
|
|
|
opset(ATLBP, r0)
|
|
|
|
|
opset(ATLBR, r0)
|
|
|
|
|
opset(ATLBWI, r0)
|
|
|
|
|
opset(ATLBWR, r0)
|
|
|
|
|
|
|
|
|
|
case ACMPEQF:
|
|
|
|
|
opset(ACMPGTF, r0)
|
|
|
|
|
opset(ACMPGTD, r0)
|
|
|
|
|
opset(ACMPGEF, r0)
|
|
|
|
|
opset(ACMPGED, r0)
|
|
|
|
|
opset(ACMPEQD, r0)
|
|
|
|
|
|
|
|
|
|
case ABFPT:
|
|
|
|
|
opset(ABFPF, r0)
|
|
|
|
|
|
|
|
|
|
case AMOVWL:
|
|
|
|
|
opset(AMOVWR, r0)
|
2016-10-18 23:50:37 +02:00
|
|
|
|
|
|
|
|
case AMOVVL:
|
2015-09-10 11:13:00 -04:00
|
|
|
opset(AMOVVR, r0)
|
|
|
|
|
|
cmd/asm: add MIPS MSA LD/ST/LDI support for mips64x
This CL adding primitive asm support of MIPS MSA by introducing
new sets of register W0-W31 (C_WREG) and 12 new instructions:
* VMOV{B,H,W,D} ADDCONST, WREG (Vector load immediate)
* VMOV{B,H,W,D} SOREG, WREG (Vector load)
* VMOV{B,H,W,D} WREG, SOREG (Vector store)
Ref: MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module
Change-Id: I3362c59a73c82c94769c18a19a0bee7e5029217d
Reviewed-on: https://go-review.googlesource.com/c/go/+/215723
Run-TryBot: Meng Zhuo <mengzhuo1203@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-03-03 23:05:32 +08:00
|
|
|
case AVMOVB:
|
|
|
|
|
opset(AVMOVH, r0)
|
|
|
|
|
opset(AVMOVW, r0)
|
|
|
|
|
opset(AVMOVD, r0)
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case AMOVW,
|
|
|
|
|
AMOVD,
|
|
|
|
|
AMOVF,
|
|
|
|
|
AMOVV,
|
|
|
|
|
ABREAK,
|
|
|
|
|
ARFE,
|
|
|
|
|
AJAL,
|
|
|
|
|
AJMP,
|
|
|
|
|
AMOVWU,
|
2016-10-18 23:50:37 +02:00
|
|
|
ALL,
|
2017-04-11 10:39:55 -04:00
|
|
|
ALLV,
|
2016-10-18 23:50:37 +02:00
|
|
|
ASC,
|
2017-04-11 10:39:55 -04:00
|
|
|
ASCV,
|
2018-01-25 11:46:06 -05:00
|
|
|
ANEGW,
|
|
|
|
|
ANEGV,
|
2015-09-05 20:27:00 -04:00
|
|
|
AWORD,
|
|
|
|
|
obj.ANOP,
|
|
|
|
|
obj.ATEXT,
|
|
|
|
|
obj.AUNDEF,
|
|
|
|
|
obj.AFUNCDATA,
|
|
|
|
|
obj.APCDATA,
|
|
|
|
|
obj.ADUFFZERO,
|
|
|
|
|
obj.ADUFFCOPY:
|
|
|
|
|
break
|
2016-10-18 23:50:37 +02:00
|
|
|
|
|
|
|
|
case ACMOVN:
|
|
|
|
|
opset(ACMOVZ, r0)
|
|
|
|
|
|
|
|
|
|
case ACMOVT:
|
|
|
|
|
opset(ACMOVF, r0)
|
|
|
|
|
|
|
|
|
|
case ACLO:
|
|
|
|
|
opset(ACLZ, r0)
|
|
|
|
|
|
|
|
|
|
case ATEQ:
|
|
|
|
|
opset(ATNE, r0)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func OP(x uint32, y uint32) uint32 {
|
|
|
|
|
return x<<3 | y<<0
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func SP(x uint32, y uint32) uint32 {
|
|
|
|
|
return x<<29 | y<<26
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func BCOND(x uint32, y uint32) uint32 {
|
|
|
|
|
return x<<19 | y<<16
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func MMU(x uint32, y uint32) uint32 {
|
|
|
|
|
return SP(2, 0) | 16<<21 | x<<3 | y<<0
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func FPF(x uint32, y uint32) uint32 {
|
|
|
|
|
return SP(2, 1) | 16<<21 | x<<3 | y<<0
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func FPD(x uint32, y uint32) uint32 {
|
|
|
|
|
return SP(2, 1) | 17<<21 | x<<3 | y<<0
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func FPW(x uint32, y uint32) uint32 {
|
|
|
|
|
return SP(2, 1) | 20<<21 | x<<3 | y<<0
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func FPV(x uint32, y uint32) uint32 {
|
|
|
|
|
return SP(2, 1) | 21<<21 | x<<3 | y<<0
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
|
|
|
|
|
return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
|
|
|
|
|
return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
|
|
|
|
|
return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
|
|
|
|
|
return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
func OP_JMP(op uint32, i uint32) uint32 {
|
|
|
|
|
return op | i&0x3FFFFFF
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
cmd/asm: add MIPS MSA LD/ST/LDI support for mips64x
This CL adding primitive asm support of MIPS MSA by introducing
new sets of register W0-W31 (C_WREG) and 12 new instructions:
* VMOV{B,H,W,D} ADDCONST, WREG (Vector load immediate)
* VMOV{B,H,W,D} SOREG, WREG (Vector load)
* VMOV{B,H,W,D} WREG, SOREG (Vector store)
Ref: MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module
Change-Id: I3362c59a73c82c94769c18a19a0bee7e5029217d
Reviewed-on: https://go-review.googlesource.com/c/go/+/215723
Run-TryBot: Meng Zhuo <mengzhuo1203@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-03-03 23:05:32 +08:00
|
|
|
func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
|
|
|
|
|
return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
|
|
|
|
|
return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
2015-09-05 20:27:00 -04:00
|
|
|
o1 := uint32(0)
|
|
|
|
|
o2 := uint32(0)
|
|
|
|
|
o3 := uint32(0)
|
|
|
|
|
o4 := uint32(0)
|
|
|
|
|
|
2016-10-18 23:50:37 +02:00
|
|
|
add := AADDU
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.ctxt.Arch.Family == sys.MIPS64 {
|
2016-10-18 23:50:37 +02:00
|
|
|
add = AADDVU
|
|
|
|
|
}
|
2015-09-05 20:27:00 -04:00
|
|
|
switch o.type_ {
|
|
|
|
|
default:
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("unknown type %d %v", o.type_)
|
2015-09-05 20:27:00 -04:00
|
|
|
prasm(p)
|
|
|
|
|
|
|
|
|
|
case 0: /* pseudo ops */
|
|
|
|
|
break
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
|
2016-04-27 22:18:02 -04:00
|
|
|
a := AOR
|
2017-04-10 14:15:57 -07:00
|
|
|
if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 {
|
2019-03-05 01:24:35 +00:00
|
|
|
// on MIPS64, most of the 32-bit instructions have unpredictable behavior,
|
|
|
|
|
// but SLL is special that the result is always sign-extended to 64-bit.
|
|
|
|
|
a = ASLL
|
2016-04-27 22:18:02 -04:00
|
|
|
}
|
2019-03-05 01:24:35 +00:00
|
|
|
o1 = OP_RRR(c.oprrr(a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 2: /* add/sub r1,[r2],r3 */
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.Reg)
|
2018-01-25 11:46:06 -05:00
|
|
|
if p.As == ANEGW || p.As == ANEGV {
|
|
|
|
|
r = REGZERO
|
|
|
|
|
}
|
2015-09-05 20:27:00 -04:00
|
|
|
if r == 0 {
|
|
|
|
|
r = int(p.To.Reg)
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 3: /* mov $soreg, r ==> or/add $i,o,r */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
r := int(p.From.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(o.param)
|
|
|
|
|
}
|
2016-10-18 23:50:37 +02:00
|
|
|
a := add
|
2015-09-10 11:13:00 -04:00
|
|
|
if o.a1 == C_ANDCON {
|
|
|
|
|
a = AOR
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 4: /* add $scon,[r1],r2 */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
r := int(p.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(p.To.Reg)
|
|
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
case 5: /* syscall */
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = c.oprrr(p.As)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 6: /* beq r1,[r2],sbra */
|
|
|
|
|
v := int32(0)
|
|
|
|
|
if p.Pcond == nil {
|
|
|
|
|
v = int32(-4) >> 2
|
|
|
|
|
} else {
|
|
|
|
|
v = int32(p.Pcond.Pc-p.Pc-4) >> 2
|
|
|
|
|
}
|
|
|
|
|
if (v<<16)>>16 != v {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("short branch too far\n%v", p)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
|
2015-09-10 11:13:00 -04:00
|
|
|
// for ABFPT and ABFPF only: always fill delay slot with 0
|
|
|
|
|
// see comments in func preprocess for details.
|
|
|
|
|
o2 = 0
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 7: /* mov r, soreg ==> sw o(r) */
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.To.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(o.param)
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.To)
|
|
|
|
|
o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 8: /* mov soreg, r ==> lw o(r) */
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.From.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(o.param)
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
|
|
|
|
o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 9: /* sll r1,[r2],r3 */
|
|
|
|
|
r := int(p.Reg)
|
2015-09-05 20:27:00 -04:00
|
|
|
|
|
|
|
|
if r == 0 {
|
2015-09-10 11:13:00 -04:00
|
|
|
r = int(p.To.Reg)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
|
2015-09-10 11:13:00 -04:00
|
|
|
|
|
|
|
|
case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
2015-09-10 11:13:00 -04:00
|
|
|
a := AOR
|
|
|
|
|
if v < 0 {
|
|
|
|
|
a = AADDU
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(p.To.Reg)
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 11: /* jmp lbra */
|
2015-09-05 20:27:00 -04:00
|
|
|
v := int32(0)
|
2017-04-10 14:15:57 -07:00
|
|
|
if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
|
2015-09-10 11:13:00 -04:00
|
|
|
// use PC-relative branch for short branches
|
|
|
|
|
// BEQ R0, R0, sbra
|
|
|
|
|
if p.Pcond == nil {
|
|
|
|
|
v = int32(-4) >> 2
|
|
|
|
|
} else {
|
|
|
|
|
v = int32(p.Pcond.Pc-p.Pc-4) >> 2
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
if (v<<16)>>16 == v {
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
|
2015-09-10 11:13:00 -04:00
|
|
|
break
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
if p.Pcond == nil {
|
|
|
|
|
v = int32(p.Pc) >> 2
|
2015-09-05 20:27:00 -04:00
|
|
|
} else {
|
2015-09-10 11:13:00 -04:00
|
|
|
v = int32(p.Pcond.Pc) >> 2
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_JMP(c.opirr(p.As), uint32(v))
|
2015-09-10 11:13:00 -04:00
|
|
|
if p.To.Sym == nil {
|
2017-04-18 10:18:34 -07:00
|
|
|
p.To.Sym = c.cursym.Func.Text.From.Sym
|
2015-09-10 11:13:00 -04:00
|
|
|
p.To.Offset = p.Pcond.Pc
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
rel := obj.Addrel(c.cursym)
|
|
|
|
|
rel.Off = int32(c.pc)
|
2015-09-10 11:13:00 -04:00
|
|
|
rel.Siz = 4
|
|
|
|
|
rel.Sym = p.To.Sym
|
|
|
|
|
rel.Add = p.To.Offset
|
|
|
|
|
if p.As == AJAL {
|
2017-04-18 12:53:25 -07:00
|
|
|
rel.Type = objabi.R_CALLMIPS
|
2015-09-05 20:27:00 -04:00
|
|
|
} else {
|
2017-04-18 12:53:25 -07:00
|
|
|
rel.Type = objabi.R_JMPMIPS
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 12: /* movbs r,r */
|
2019-10-26 22:49:13 -04:00
|
|
|
// NOTE: this case does not use REGTMP. If it ever does,
|
|
|
|
|
// remove the NOTUSETMP flag in optab.
|
2015-09-10 11:13:00 -04:00
|
|
|
v := 16
|
|
|
|
|
if p.As == AMOVB {
|
|
|
|
|
v = 24
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
|
|
|
|
|
o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 13: /* movbu r,r */
|
|
|
|
|
if p.As == AMOVBU {
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
} else {
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 14: /* movwu r,r */
|
2019-10-26 22:49:13 -04:00
|
|
|
// NOTE: this case does not use REGTMP. If it ever does,
|
|
|
|
|
// remove the NOTUSETMP flag in optab.
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
|
|
|
|
|
o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2016-10-18 23:50:37 +02:00
|
|
|
case 15: /* teq $c r,r */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
2016-10-18 23:50:37 +02:00
|
|
|
r := int(p.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = REGZERO
|
|
|
|
|
}
|
|
|
|
|
/* only use 10 bits of trap code */
|
2019-03-03 16:42:08 +00:00
|
|
|
o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(r), uint32(p.To.Reg))
|
2016-10-18 23:50:37 +02:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 16: /* sll $c,[r1],r2 */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(p.To.Reg)
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
/* OP_SRR will use only the low 5 bits of the shift value */
|
|
|
|
|
if v >= 32 && vshift(p.As) {
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg))
|
2015-09-10 11:13:00 -04:00
|
|
|
} else {
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2016-10-18 23:50:37 +02:00
|
|
|
case 17:
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
|
2016-10-18 23:50:37 +02:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 18: /* jmp [r1],0(r2) */
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(o.param)
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
|
2020-04-02 22:12:38 -04:00
|
|
|
if p.As == obj.ACALL {
|
|
|
|
|
rel := obj.Addrel(c.cursym)
|
|
|
|
|
rel.Off = int32(c.pc)
|
|
|
|
|
rel.Siz = 0
|
|
|
|
|
rel.Type = objabi.R_CALLIND
|
|
|
|
|
}
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 19: /* mov $lcon,r ==> lu+or */
|
2019-10-26 22:49:13 -04:00
|
|
|
// NOTE: this case does not use REGTMP. If it ever does,
|
|
|
|
|
// remove the NOTUSETMP flag in optab.
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
|
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
|
|
|
|
|
o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 20: /* mov lo/hi,r */
|
|
|
|
|
a := OP(2, 0) /* mfhi */
|
|
|
|
|
if p.From.Reg == REG_LO {
|
|
|
|
|
a = OP(2, 2) /* mflo */
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 21: /* mov r,lo/hi */
|
|
|
|
|
a := OP(2, 1) /* mthi */
|
|
|
|
|
if p.To.Reg == REG_LO {
|
|
|
|
|
a = OP(2, 3) /* mtlo */
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2016-10-18 23:50:37 +02:00
|
|
|
case 22: /* mul r1,r2 [r3]*/
|
|
|
|
|
if p.To.Reg != 0 {
|
|
|
|
|
r := int(p.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(p.To.Reg)
|
|
|
|
|
}
|
|
|
|
|
a := SP(3, 4) | 2 /* mul */
|
|
|
|
|
o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
|
|
|
|
|
} else {
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
|
2016-10-18 23:50:37 +02:00
|
|
|
}
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 23: /* add $lcon,r1,r2 ==> lu+or+add */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
|
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
|
|
|
|
|
o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
|
2015-09-10 11:13:00 -04:00
|
|
|
r := int(p.Reg)
|
2015-09-05 20:27:00 -04:00
|
|
|
if r == 0 {
|
2015-09-10 11:13:00 -04:00
|
|
|
r = int(p.To.Reg)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 24: /* mov $ucon,r ==> lu r */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
|
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
|
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
|
2015-09-10 11:13:00 -04:00
|
|
|
r := int(p.Reg)
|
2015-09-05 20:27:00 -04:00
|
|
|
if r == 0 {
|
2015-09-10 11:13:00 -04:00
|
|
|
r = int(p.To.Reg)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
|
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
|
|
|
|
|
o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.From.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(o.param)
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.From.Reg)
|
|
|
|
|
if r == 0 {
|
2015-09-10 11:13:00 -04:00
|
|
|
r = int(o.param)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
a := -AMOVF
|
2015-09-10 11:13:00 -04:00
|
|
|
if p.As == AMOVD {
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
a = -AMOVD
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
switch o.size {
|
2016-04-27 22:18:02 -04:00
|
|
|
case 12:
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
|
|
|
|
|
o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
|
|
|
|
|
o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 4:
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.To)
|
2015-09-10 11:13:00 -04:00
|
|
|
r := int(p.To.Reg)
|
2015-09-05 20:27:00 -04:00
|
|
|
if r == 0 {
|
2015-09-10 11:13:00 -04:00
|
|
|
r = int(o.param)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
a := AMOVF
|
|
|
|
|
if p.As == AMOVD {
|
|
|
|
|
a = AMOVD
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
switch o.size {
|
2016-04-27 22:18:02 -04:00
|
|
|
case 12:
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
|
|
|
|
|
o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
|
|
|
|
|
o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 4:
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 30: /* movw r,fr */
|
|
|
|
|
a := SP(2, 1) | (4 << 21) /* mtc1 */
|
|
|
|
|
o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 31: /* movw fr,r */
|
|
|
|
|
a := SP(2, 1) | (0 << 21) /* mtc1 */
|
|
|
|
|
o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 32: /* fadd fr1,[fr2],fr3 */
|
2015-09-05 20:27:00 -04:00
|
|
|
r := int(p.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(p.To.Reg)
|
|
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 33: /* fabs fr1, fr3 */
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
2015-09-10 11:13:00 -04:00
|
|
|
a := AADDU
|
|
|
|
|
if o.a1 == C_ANDCON {
|
|
|
|
|
a = AOR
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
|
2015-09-10 11:13:00 -04:00
|
|
|
o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2016-04-27 22:18:02 -04:00
|
|
|
case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.To)
|
2015-09-10 11:13:00 -04:00
|
|
|
r := int(p.To.Reg)
|
2015-09-05 20:27:00 -04:00
|
|
|
if r == 0 {
|
2015-09-10 11:13:00 -04:00
|
|
|
r = int(o.param)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
|
|
|
|
|
o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
|
|
|
|
|
o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2016-04-27 22:18:02 -04:00
|
|
|
case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
|
2017-04-10 14:15:57 -07:00
|
|
|
v := c.regoff(&p.From)
|
2015-09-10 11:13:00 -04:00
|
|
|
r := int(p.From.Reg)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
r = int(o.param)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
|
|
|
|
|
o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
|
|
|
|
|
o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 37: /* movw r,mr */
|
|
|
|
|
a := SP(2, 0) | (4 << 21) /* mtc0 */
|
|
|
|
|
if p.As == AMOVV {
|
|
|
|
|
a = SP(2, 0) | (5 << 21) /* dmtc0 */
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 38: /* movw mr,r */
|
|
|
|
|
a := SP(2, 0) | (0 << 21) /* mfc0 */
|
|
|
|
|
if p.As == AMOVV {
|
|
|
|
|
a = SP(2, 0) | (1 << 21) /* dmfc0 */
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 40: /* word */
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = uint32(c.regoff(&p.From))
|
2015-09-05 20:27:00 -04:00
|
|
|
|
2015-09-10 11:13:00 -04:00
|
|
|
case 41: /* movw f,fcr */
|
2019-10-26 22:48:15 -04:00
|
|
|
o1 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
|
2015-09-10 11:13:00 -04:00
|
|
|
|
|
|
|
|
case 42: /* movw fcr,r */
|
|
|
|
|
o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
|
|
|
|
|
|
|
|
|
|
case 47: /* movv r,fr */
|
|
|
|
|
a := SP(2, 1) | (5 << 21) /* dmtc1 */
|
|
|
|
|
o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
|
|
|
|
|
|
|
|
|
|
case 48: /* movv fr,r */
|
|
|
|
|
a := SP(2, 1) | (1 << 21) /* dmtc1 */
|
|
|
|
|
o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
|
|
|
|
|
|
|
|
|
|
case 49: /* undef */
|
2016-04-27 22:18:02 -04:00
|
|
|
o1 = 52 /* trap -- teq r0, r0 */
|
2015-09-10 11:13:00 -04:00
|
|
|
|
|
|
|
|
/* relocation operations */
|
2016-04-27 22:18:02 -04:00
|
|
|
case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
|
|
|
|
|
rel := obj.Addrel(c.cursym)
|
|
|
|
|
rel.Off = int32(c.pc)
|
2016-04-27 22:18:02 -04:00
|
|
|
rel.Siz = 4
|
2015-09-10 11:13:00 -04:00
|
|
|
rel.Sym = p.To.Sym
|
|
|
|
|
rel.Add = p.To.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel.Type = objabi.R_ADDRMIPSU
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
|
|
|
|
|
rel2 := obj.Addrel(c.cursym)
|
|
|
|
|
rel2.Off = int32(c.pc + 4)
|
2016-04-27 22:18:02 -04:00
|
|
|
rel2.Siz = 4
|
|
|
|
|
rel2.Sym = p.To.Sym
|
|
|
|
|
rel2.Add = p.To.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel2.Type = objabi.R_ADDRMIPS
|
2016-04-27 22:18:02 -04:00
|
|
|
|
2016-10-18 23:50:37 +02:00
|
|
|
if o.size == 12 {
|
|
|
|
|
o3 = o2
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
|
2016-10-18 23:50:37 +02:00
|
|
|
rel2.Off += 4
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-27 22:18:02 -04:00
|
|
|
case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
|
|
|
|
|
rel := obj.Addrel(c.cursym)
|
|
|
|
|
rel.Off = int32(c.pc)
|
2016-04-27 22:18:02 -04:00
|
|
|
rel.Siz = 4
|
2015-09-10 11:13:00 -04:00
|
|
|
rel.Sym = p.From.Sym
|
|
|
|
|
rel.Add = p.From.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel.Type = objabi.R_ADDRMIPSU
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
|
|
|
|
|
rel2 := obj.Addrel(c.cursym)
|
|
|
|
|
rel2.Off = int32(c.pc + 4)
|
2016-04-27 22:18:02 -04:00
|
|
|
rel2.Siz = 4
|
|
|
|
|
rel2.Sym = p.From.Sym
|
|
|
|
|
rel2.Add = p.From.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel2.Type = objabi.R_ADDRMIPS
|
2016-04-27 22:18:02 -04:00
|
|
|
|
2016-10-18 23:50:37 +02:00
|
|
|
if o.size == 12 {
|
|
|
|
|
o3 = o2
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
|
2016-10-18 23:50:37 +02:00
|
|
|
rel2.Off += 4
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-27 22:18:02 -04:00
|
|
|
case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
|
2019-10-26 22:49:13 -04:00
|
|
|
// NOTE: this case does not use REGTMP. If it ever does,
|
|
|
|
|
// remove the NOTUSETMP flag in optab.
|
2017-04-10 14:15:57 -07:00
|
|
|
o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
|
|
|
|
|
rel := obj.Addrel(c.cursym)
|
|
|
|
|
rel.Off = int32(c.pc)
|
2016-04-27 22:18:02 -04:00
|
|
|
rel.Siz = 4
|
|
|
|
|
rel.Sym = p.From.Sym
|
|
|
|
|
rel.Add = p.From.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel.Type = objabi.R_ADDRMIPSU
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
|
|
|
|
|
rel2 := obj.Addrel(c.cursym)
|
|
|
|
|
rel2.Off = int32(c.pc + 4)
|
2016-04-27 22:18:02 -04:00
|
|
|
rel2.Siz = 4
|
|
|
|
|
rel2.Sym = p.From.Sym
|
|
|
|
|
rel2.Add = p.From.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel2.Type = objabi.R_ADDRMIPS
|
2016-04-27 22:18:14 -04:00
|
|
|
|
2016-10-18 23:50:37 +02:00
|
|
|
if o.size == 12 {
|
|
|
|
|
o3 = o2
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
|
2016-10-18 23:50:37 +02:00
|
|
|
rel2.Off += 4
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-27 22:18:14 -04:00
|
|
|
case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
|
|
|
|
|
// clobbers R3 !
|
|
|
|
|
// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
|
2019-10-26 22:49:13 -04:00
|
|
|
// NOTE: this case does not use REGTMP. If it ever does,
|
|
|
|
|
// remove the NOTUSETMP flag in optab.
|
2016-04-27 22:18:14 -04:00
|
|
|
o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
|
|
|
|
|
rel := obj.Addrel(c.cursym)
|
|
|
|
|
rel.Off = int32(c.pc + 4)
|
2016-04-27 22:18:14 -04:00
|
|
|
rel.Siz = 4
|
|
|
|
|
rel.Sym = p.To.Sym
|
|
|
|
|
rel.Add = p.To.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel.Type = objabi.R_ADDRMIPSTLS
|
2016-04-27 22:18:14 -04:00
|
|
|
|
|
|
|
|
case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
|
|
|
|
|
// clobbers R3 !
|
2019-10-26 22:49:13 -04:00
|
|
|
// NOTE: this case does not use REGTMP. If it ever does,
|
|
|
|
|
// remove the NOTUSETMP flag in optab.
|
2016-04-27 22:18:14 -04:00
|
|
|
o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
|
|
|
|
|
rel := obj.Addrel(c.cursym)
|
|
|
|
|
rel.Off = int32(c.pc + 4)
|
2016-04-27 22:18:14 -04:00
|
|
|
rel.Siz = 4
|
|
|
|
|
rel.Sym = p.From.Sym
|
|
|
|
|
rel.Add = p.From.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel.Type = objabi.R_ADDRMIPSTLS
|
2016-04-27 22:18:14 -04:00
|
|
|
|
|
|
|
|
case 55: /* mov $tlsvar, r ==> rdhwr + add */
|
|
|
|
|
// clobbers R3 !
|
2019-10-26 22:49:13 -04:00
|
|
|
// NOTE: this case does not use REGTMP. If it ever does,
|
|
|
|
|
// remove the NOTUSETMP flag in optab.
|
2016-04-27 22:18:14 -04:00
|
|
|
o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
|
2017-04-10 14:15:57 -07:00
|
|
|
o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
|
|
|
|
|
rel := obj.Addrel(c.cursym)
|
|
|
|
|
rel.Off = int32(c.pc + 4)
|
2016-04-27 22:18:14 -04:00
|
|
|
rel.Siz = 4
|
|
|
|
|
rel.Sym = p.From.Sym
|
|
|
|
|
rel.Add = p.From.Offset
|
2017-04-18 12:53:25 -07:00
|
|
|
rel.Type = objabi.R_ADDRMIPSTLS
|
cmd/asm: add MIPS MSA LD/ST/LDI support for mips64x
This CL adding primitive asm support of MIPS MSA by introducing
new sets of register W0-W31 (C_WREG) and 12 new instructions:
* VMOV{B,H,W,D} ADDCONST, WREG (Vector load immediate)
* VMOV{B,H,W,D} SOREG, WREG (Vector load)
* VMOV{B,H,W,D} WREG, SOREG (Vector store)
Ref: MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module
Change-Id: I3362c59a73c82c94769c18a19a0bee7e5029217d
Reviewed-on: https://go-review.googlesource.com/c/go/+/215723
Run-TryBot: Meng Zhuo <mengzhuo1203@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-03-03 23:05:32 +08:00
|
|
|
|
|
|
|
|
case 56: /* vmov{b,h,w,d} $scon, wr */
|
|
|
|
|
|
|
|
|
|
v := c.regoff(&p.From)
|
|
|
|
|
o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
|
|
|
|
|
|
|
|
|
|
case 57: /* vld $soreg, wr */
|
|
|
|
|
v := c.lsoffset(p.As, c.regoff(&p.From))
|
|
|
|
|
o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
|
|
|
|
|
|
|
|
|
|
case 58: /* vst wr, $soreg */
|
|
|
|
|
v := c.lsoffset(p.As, c.regoff(&p.To))
|
|
|
|
|
o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out[0] = o1
|
|
|
|
|
out[1] = o2
|
|
|
|
|
out[2] = o3
|
|
|
|
|
out[3] = o4
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
func (c *ctxt0) vregoff(a *obj.Addr) int64 {
|
|
|
|
|
c.instoffset = 0
|
|
|
|
|
c.aclass(a)
|
|
|
|
|
return c.instoffset
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
func (c *ctxt0) regoff(a *obj.Addr) int32 {
|
|
|
|
|
return int32(c.vregoff(a))
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
func (c *ctxt0) oprrr(a obj.As) uint32 {
|
2015-09-05 20:27:00 -04:00
|
|
|
switch a {
|
|
|
|
|
case AADD:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(4, 0)
|
|
|
|
|
case AADDU:
|
|
|
|
|
return OP(4, 1)
|
|
|
|
|
case ASGT:
|
|
|
|
|
return OP(5, 2)
|
|
|
|
|
case ASGTU:
|
|
|
|
|
return OP(5, 3)
|
2015-09-05 20:27:00 -04:00
|
|
|
case AAND:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(4, 4)
|
2015-09-05 20:27:00 -04:00
|
|
|
case AOR:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(4, 5)
|
|
|
|
|
case AXOR:
|
|
|
|
|
return OP(4, 6)
|
2015-09-05 20:27:00 -04:00
|
|
|
case ASUB:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(4, 2)
|
2018-01-25 11:46:06 -05:00
|
|
|
case ASUBU, ANEGW:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(4, 3)
|
|
|
|
|
case ANOR:
|
|
|
|
|
return OP(4, 7)
|
|
|
|
|
case ASLL:
|
|
|
|
|
return OP(0, 4)
|
|
|
|
|
case ASRL:
|
|
|
|
|
return OP(0, 6)
|
|
|
|
|
case ASRA:
|
|
|
|
|
return OP(0, 7)
|
|
|
|
|
case ASLLV:
|
|
|
|
|
return OP(2, 4)
|
|
|
|
|
case ASRLV:
|
|
|
|
|
return OP(2, 6)
|
|
|
|
|
case ASRAV:
|
|
|
|
|
return OP(2, 7)
|
|
|
|
|
case AADDV:
|
|
|
|
|
return OP(5, 4)
|
|
|
|
|
case AADDVU:
|
|
|
|
|
return OP(5, 5)
|
2015-09-05 20:27:00 -04:00
|
|
|
case ASUBV:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(5, 6)
|
2018-01-25 11:46:06 -05:00
|
|
|
case ASUBVU, ANEGV:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(5, 7)
|
|
|
|
|
case AREM,
|
|
|
|
|
ADIV:
|
|
|
|
|
return OP(3, 2)
|
|
|
|
|
case AREMU,
|
|
|
|
|
ADIVU:
|
|
|
|
|
return OP(3, 3)
|
|
|
|
|
case AMUL:
|
|
|
|
|
return OP(3, 0)
|
|
|
|
|
case AMULU:
|
|
|
|
|
return OP(3, 1)
|
|
|
|
|
case AREMV,
|
|
|
|
|
ADIVV:
|
|
|
|
|
return OP(3, 6)
|
|
|
|
|
case AREMVU,
|
|
|
|
|
ADIVVU:
|
|
|
|
|
return OP(3, 7)
|
|
|
|
|
case AMULV:
|
|
|
|
|
return OP(3, 4)
|
|
|
|
|
case AMULVU:
|
|
|
|
|
return OP(3, 5)
|
|
|
|
|
|
|
|
|
|
case AJMP:
|
|
|
|
|
return OP(1, 0)
|
|
|
|
|
case AJAL:
|
|
|
|
|
return OP(1, 1)
|
|
|
|
|
|
|
|
|
|
case ABREAK:
|
|
|
|
|
return OP(1, 5)
|
|
|
|
|
case ASYSCALL:
|
|
|
|
|
return OP(1, 4)
|
|
|
|
|
case ATLBP:
|
|
|
|
|
return MMU(1, 0)
|
|
|
|
|
case ATLBR:
|
|
|
|
|
return MMU(0, 1)
|
|
|
|
|
case ATLBWI:
|
|
|
|
|
return MMU(0, 2)
|
|
|
|
|
case ATLBWR:
|
|
|
|
|
return MMU(0, 6)
|
|
|
|
|
case ARFE:
|
|
|
|
|
return MMU(2, 0)
|
|
|
|
|
|
|
|
|
|
case ADIVF:
|
|
|
|
|
return FPF(0, 3)
|
|
|
|
|
case ADIVD:
|
|
|
|
|
return FPD(0, 3)
|
|
|
|
|
case AMULF:
|
|
|
|
|
return FPF(0, 2)
|
|
|
|
|
case AMULD:
|
|
|
|
|
return FPD(0, 2)
|
|
|
|
|
case ASUBF:
|
|
|
|
|
return FPF(0, 1)
|
|
|
|
|
case ASUBD:
|
|
|
|
|
return FPD(0, 1)
|
|
|
|
|
case AADDF:
|
|
|
|
|
return FPF(0, 0)
|
|
|
|
|
case AADDD:
|
|
|
|
|
return FPD(0, 0)
|
|
|
|
|
case ATRUNCFV:
|
|
|
|
|
return FPF(1, 1)
|
|
|
|
|
case ATRUNCDV:
|
|
|
|
|
return FPD(1, 1)
|
|
|
|
|
case ATRUNCFW:
|
|
|
|
|
return FPF(1, 5)
|
|
|
|
|
case ATRUNCDW:
|
|
|
|
|
return FPD(1, 5)
|
|
|
|
|
case AMOVFV:
|
|
|
|
|
return FPF(4, 5)
|
|
|
|
|
case AMOVDV:
|
|
|
|
|
return FPD(4, 5)
|
|
|
|
|
case AMOVVF:
|
|
|
|
|
return FPV(4, 0)
|
|
|
|
|
case AMOVVD:
|
|
|
|
|
return FPV(4, 1)
|
|
|
|
|
case AMOVFW:
|
|
|
|
|
return FPF(4, 4)
|
|
|
|
|
case AMOVDW:
|
|
|
|
|
return FPD(4, 4)
|
|
|
|
|
case AMOVWF:
|
|
|
|
|
return FPW(4, 0)
|
|
|
|
|
case AMOVDF:
|
|
|
|
|
return FPD(4, 0)
|
|
|
|
|
case AMOVWD:
|
|
|
|
|
return FPW(4, 1)
|
|
|
|
|
case AMOVFD:
|
|
|
|
|
return FPF(4, 1)
|
|
|
|
|
case AABSF:
|
|
|
|
|
return FPF(0, 5)
|
|
|
|
|
case AABSD:
|
|
|
|
|
return FPD(0, 5)
|
|
|
|
|
case AMOVF:
|
|
|
|
|
return FPF(0, 6)
|
|
|
|
|
case AMOVD:
|
|
|
|
|
return FPD(0, 6)
|
|
|
|
|
case ANEGF:
|
|
|
|
|
return FPF(0, 7)
|
|
|
|
|
case ANEGD:
|
|
|
|
|
return FPD(0, 7)
|
|
|
|
|
case ACMPEQF:
|
|
|
|
|
return FPF(6, 2)
|
|
|
|
|
case ACMPEQD:
|
|
|
|
|
return FPD(6, 2)
|
|
|
|
|
case ACMPGTF:
|
|
|
|
|
return FPF(7, 4)
|
|
|
|
|
case ACMPGTD:
|
|
|
|
|
return FPD(7, 4)
|
|
|
|
|
case ACMPGEF:
|
|
|
|
|
return FPF(7, 6)
|
|
|
|
|
case ACMPGED:
|
|
|
|
|
return FPD(7, 6)
|
2016-10-18 23:50:37 +02:00
|
|
|
|
|
|
|
|
case ASQRTF:
|
|
|
|
|
return FPF(0, 4)
|
|
|
|
|
case ASQRTD:
|
|
|
|
|
return FPD(0, 4)
|
|
|
|
|
|
|
|
|
|
case ASYNC:
|
|
|
|
|
return OP(1, 7)
|
2017-04-11 10:39:55 -04:00
|
|
|
case ANOOP:
|
|
|
|
|
return 0
|
2016-10-18 23:50:37 +02:00
|
|
|
|
|
|
|
|
case ACMOVN:
|
|
|
|
|
return OP(1, 3)
|
|
|
|
|
case ACMOVZ:
|
|
|
|
|
return OP(1, 2)
|
|
|
|
|
case ACMOVT:
|
|
|
|
|
return OP(0, 1) | (1 << 16)
|
|
|
|
|
case ACMOVF:
|
|
|
|
|
return OP(0, 1) | (0 << 16)
|
|
|
|
|
case ACLO:
|
|
|
|
|
return SP(3, 4) | OP(4, 1)
|
|
|
|
|
case ACLZ:
|
|
|
|
|
return SP(3, 4) | OP(4, 0)
|
2019-03-15 08:26:53 +00:00
|
|
|
case AMADD:
|
|
|
|
|
return SP(3, 4) | OP(0, 0)
|
|
|
|
|
case AMSUB:
|
|
|
|
|
return SP(3, 4) | OP(0, 4)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
if a < 0 {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("bad rrr opcode -%v", -a)
|
2015-09-10 11:13:00 -04:00
|
|
|
} else {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("bad rrr opcode %v", a)
|
2015-09-10 11:13:00 -04:00
|
|
|
}
|
2015-09-05 20:27:00 -04:00
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 14:15:57 -07:00
|
|
|
func (c *ctxt0) opirr(a obj.As) uint32 {
|
2015-09-05 20:27:00 -04:00
|
|
|
switch a {
|
|
|
|
|
case AADD:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(1, 0)
|
|
|
|
|
case AADDU:
|
|
|
|
|
return SP(1, 1)
|
|
|
|
|
case ASGT:
|
|
|
|
|
return SP(1, 2)
|
|
|
|
|
case ASGTU:
|
|
|
|
|
return SP(1, 3)
|
|
|
|
|
case AAND:
|
|
|
|
|
return SP(1, 4)
|
2015-09-05 20:27:00 -04:00
|
|
|
case AOR:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(1, 5)
|
2015-09-05 20:27:00 -04:00
|
|
|
case AXOR:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(1, 6)
|
2016-03-07 13:45:52 -08:00
|
|
|
case ALUI:
|
|
|
|
|
return SP(1, 7)
|
2015-09-10 11:13:00 -04:00
|
|
|
case ASLL:
|
|
|
|
|
return OP(0, 0)
|
|
|
|
|
case ASRL:
|
|
|
|
|
return OP(0, 2)
|
|
|
|
|
case ASRA:
|
|
|
|
|
return OP(0, 3)
|
|
|
|
|
case AADDV:
|
|
|
|
|
return SP(3, 0)
|
|
|
|
|
case AADDVU:
|
|
|
|
|
return SP(3, 1)
|
|
|
|
|
|
|
|
|
|
case AJMP:
|
|
|
|
|
return SP(0, 2)
|
|
|
|
|
case AJAL,
|
|
|
|
|
obj.ADUFFZERO,
|
|
|
|
|
obj.ADUFFCOPY:
|
|
|
|
|
return SP(0, 3)
|
|
|
|
|
case ABEQ:
|
|
|
|
|
return SP(0, 4)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABEQ:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(2, 4) /* likely */
|
|
|
|
|
case ABNE:
|
|
|
|
|
return SP(0, 5)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABNE:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(2, 5) /* likely */
|
|
|
|
|
case ABGEZ:
|
|
|
|
|
return SP(0, 1) | BCOND(0, 1)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABGEZ:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(0, 1) | BCOND(0, 3) /* likely */
|
|
|
|
|
case ABGEZAL:
|
|
|
|
|
return SP(0, 1) | BCOND(2, 1)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABGEZAL:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(0, 1) | BCOND(2, 3) /* likely */
|
|
|
|
|
case ABGTZ:
|
|
|
|
|
return SP(0, 7)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABGTZ:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(2, 7) /* likely */
|
|
|
|
|
case ABLEZ:
|
|
|
|
|
return SP(0, 6)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABLEZ:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(2, 6) /* likely */
|
|
|
|
|
case ABLTZ:
|
|
|
|
|
return SP(0, 1) | BCOND(0, 0)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABLTZ:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(0, 1) | BCOND(0, 2) /* likely */
|
|
|
|
|
case ABLTZAL:
|
|
|
|
|
return SP(0, 1) | BCOND(2, 0)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABLTZAL:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(0, 1) | BCOND(2, 2) /* likely */
|
|
|
|
|
case ABFPT:
|
|
|
|
|
return SP(2, 1) | (257 << 16)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABFPT:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(2, 1) | (259 << 16) /* likely */
|
|
|
|
|
case ABFPF:
|
|
|
|
|
return SP(2, 1) | (256 << 16)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ABFPF:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(2, 1) | (258 << 16) /* likely */
|
|
|
|
|
|
|
|
|
|
case AMOVB,
|
|
|
|
|
AMOVBU:
|
|
|
|
|
return SP(5, 0)
|
|
|
|
|
case AMOVH,
|
|
|
|
|
AMOVHU:
|
|
|
|
|
return SP(5, 1)
|
|
|
|
|
case AMOVW,
|
|
|
|
|
AMOVWU:
|
|
|
|
|
return SP(5, 3)
|
|
|
|
|
case AMOVV:
|
|
|
|
|
return SP(7, 7)
|
|
|
|
|
case AMOVF:
|
|
|
|
|
return SP(7, 1)
|
2015-09-05 20:27:00 -04:00
|
|
|
case AMOVD:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(7, 5)
|
|
|
|
|
case AMOVWL:
|
|
|
|
|
return SP(5, 2)
|
|
|
|
|
case AMOVWR:
|
|
|
|
|
return SP(5, 6)
|
|
|
|
|
case AMOVVL:
|
|
|
|
|
return SP(5, 4)
|
|
|
|
|
case AMOVVR:
|
|
|
|
|
return SP(5, 5)
|
|
|
|
|
|
|
|
|
|
case ABREAK:
|
|
|
|
|
return SP(5, 7)
|
|
|
|
|
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVWL:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(4, 2)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVWR:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(4, 6)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVVL:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(3, 2)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVVR:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(3, 3)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVB:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(4, 0)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVBU:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(4, 4)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVH:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(4, 1)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVHU:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(4, 5)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVW:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(4, 3)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVWU:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(4, 7)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVV:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(6, 7)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVF:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(6, 1)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -AMOVD:
|
2015-09-10 11:13:00 -04:00
|
|
|
return SP(6, 5)
|
|
|
|
|
|
|
|
|
|
case ASLLV:
|
|
|
|
|
return OP(7, 0)
|
|
|
|
|
case ASRLV:
|
|
|
|
|
return OP(7, 2)
|
|
|
|
|
case ASRAV:
|
|
|
|
|
return OP(7, 3)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ASLLV:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(7, 4)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ASRLV:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(7, 6)
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
case -ASRAV:
|
2015-09-10 11:13:00 -04:00
|
|
|
return OP(7, 7)
|
2016-10-18 23:50:37 +02:00
|
|
|
|
|
|
|
|
case ATEQ:
|
|
|
|
|
return OP(6, 4)
|
|
|
|
|
case ATNE:
|
|
|
|
|
return OP(6, 6)
|
|
|
|
|
case -ALL:
|
|
|
|
|
return SP(6, 0)
|
2017-04-11 10:39:55 -04:00
|
|
|
case -ALLV:
|
|
|
|
|
return SP(6, 4)
|
2016-10-18 23:50:37 +02:00
|
|
|
case ASC:
|
|
|
|
|
return SP(7, 0)
|
2017-04-11 10:39:55 -04:00
|
|
|
case ASCV:
|
|
|
|
|
return SP(7, 4)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
|
cmd/internal/obj: stop using as+ALAST as an opcode
Currently, package obj reserves a range of 1<<12 opcodes for each
target architecture. E.g., mips64 has [6<<12, 7<<12).
However, because mips.ABEQ and mips.ALAST are both within that range,
the expression mips.ABEQ+mips.ALAST in turn falls (far) outside that
range around 12<<12, meaning it could theoretically collide with
another arch's opcodes.
More practically, it's a problem because 12<<12 overflows an int16,
which hampers fixing #14692. (We could also just switch to uint16 to
avoid the overflow, but that still leaves the first problem.)
As a workaround, use Michael Hudson-Doyle's solution from
https://golang.org/cl/20182 and use negative values for these variant
instructions.
Passes toolstash -cmp for GOARCH=arm and GOARCH=mips64.
Updates #14692.
Change-Id: Iad797d10652360109fa4db19d4d1edb6529fc2c0
Reviewed-on: https://go-review.googlesource.com/20345
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-07 15:15:57 -08:00
|
|
|
if a < 0 {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("bad irr opcode -%v", -a)
|
2015-09-10 11:13:00 -04:00
|
|
|
} else {
|
2017-04-10 14:15:57 -07:00
|
|
|
c.ctxt.Diag("bad irr opcode %v", a)
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 18:00:08 -08:00
|
|
|
func vshift(a obj.As) bool {
|
2015-09-05 20:27:00 -04:00
|
|
|
switch a {
|
2015-09-10 11:13:00 -04:00
|
|
|
case ASLLV,
|
|
|
|
|
ASRLV,
|
|
|
|
|
ASRAV:
|
|
|
|
|
return true
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
2015-09-10 11:13:00 -04:00
|
|
|
return false
|
2015-09-05 20:27:00 -04:00
|
|
|
}
|
cmd/asm: add MIPS MSA LD/ST/LDI support for mips64x
This CL adding primitive asm support of MIPS MSA by introducing
new sets of register W0-W31 (C_WREG) and 12 new instructions:
* VMOV{B,H,W,D} ADDCONST, WREG (Vector load immediate)
* VMOV{B,H,W,D} SOREG, WREG (Vector load)
* VMOV{B,H,W,D} WREG, SOREG (Vector store)
Ref: MIPS Architecture for Programmers Volume IV-j: The MIPS64 SIMD Architecture Module
Change-Id: I3362c59a73c82c94769c18a19a0bee7e5029217d
Reviewed-on: https://go-review.googlesource.com/c/go/+/215723
Run-TryBot: Meng Zhuo <mengzhuo1203@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-03-03 23:05:32 +08:00
|
|
|
|
|
|
|
|
// MSA Two-bit Data Format Field Encoding
|
|
|
|
|
func (c *ctxt0) twobitdf(a obj.As) uint32 {
|
|
|
|
|
switch a {
|
|
|
|
|
case AVMOVB:
|
|
|
|
|
return 0
|
|
|
|
|
case AVMOVH:
|
|
|
|
|
return 1
|
|
|
|
|
case AVMOVW:
|
|
|
|
|
return 2
|
|
|
|
|
case AVMOVD:
|
|
|
|
|
return 3
|
|
|
|
|
default:
|
|
|
|
|
c.ctxt.Diag("unsupported data format %v", a)
|
|
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MSA Load/Store offset have to be multiple of size of data format
|
|
|
|
|
func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
|
|
|
|
|
var mod int32
|
|
|
|
|
switch a {
|
|
|
|
|
case AVMOVB:
|
|
|
|
|
mod = 1
|
|
|
|
|
case AVMOVH:
|
|
|
|
|
mod = 2
|
|
|
|
|
case AVMOVW:
|
|
|
|
|
mod = 4
|
|
|
|
|
case AVMOVD:
|
|
|
|
|
mod = 8
|
|
|
|
|
default:
|
|
|
|
|
c.ctxt.Diag("unsupported instruction:%v", a)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if o%mod != 0 {
|
|
|
|
|
c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return o / mod
|
|
|
|
|
}
|