go/src/cmd/internal/obj/ppc64/asm9.go
Rob Pike daddeb2686 cmd/internal/obj: make Rconv a global function
Clean up the obj API by making Rconv (register pretty printer) a top-level
function. This means that Dconv (operand pretty printer) doesn't need
an Rconv argument.

To do this, we make the register numbers, which are arbitrary inside an
operand (obj.Addr), disjoint sets for each architecture. Each architecture
registers (ha) a piece of the space and then the global Rconv knows which
architecture-specific printer to use.

Clean up all the code that uses Dconv.

Now register numbers are large, so a couple of fields in Addr need to go
from int8 to int16 because they sometimes hold register numbers. Clean
up their uses, which meant regenerating the yacc grammars for the
assemblers. There are changes in this CL triggered by earlier changes
to yacc, which had not been run in this directory.

There is still cleanup to do in Addr, but we're getting closer to that being
easy to do.

Change-Id: I9290ebee013b62f7d24e886743ea5a6b232990ab
Reviewed-on: https://go-review.googlesource.com/6220
Reviewed-by: Russ Cox <rsc@golang.org>
2015-02-27 03:51:33 +00:00

3323 lines
88 KiB
Go

// 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
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// 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.
package ppc64
import (
"cmd/internal/obj"
"fmt"
"log"
"sort"
)
// Instruction layout.
const (
FuncAlign = 8
)
const (
r0iszero = 1
)
type Optab struct {
as int16
a1 uint8
a2 uint8
a3 uint8
a4 uint8
type_ int8
size int8
param int16
}
var optab = []Optab{
Optab{obj.ATEXT, C_LEXT, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
Optab{obj.ATEXT, C_LEXT, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
Optab{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
Optab{obj.ATEXT, C_ADDR, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
/* move register */
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0},
Optab{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
Optab{AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
Optab{AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
Optab{AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
Optab{AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0},
Optab{AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0},
Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
Optab{AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
Optab{AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
Optab{AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
Optab{AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
Optab{AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
Optab{AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
Optab{AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, no literal */
Optab{AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
Optab{AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
Optab{AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
Optab{AANDCC, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
Optab{AANDCC, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
Optab{AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
Optab{AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
Optab{AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
Optab{AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
Optab{AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
Optab{AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
Optab{AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
Optab{AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
Optab{AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0},
Optab{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
Optab{ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0},
Optab{ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0},
Optab{AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, literal not cc (or/xor) */
Optab{AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
Optab{AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
Optab{AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
Optab{AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
Optab{AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
Optab{AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
Optab{AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, /* op r1[,r2],r3 */
Optab{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
Optab{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, /* op r2[,r1],r3 */
Optab{ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
Optab{ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
Optab{ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
Optab{ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
Optab{ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
Optab{ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0},
Optab{ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0},
Optab{ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0},
Optab{ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0},
Optab{ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
Optab{ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
Optab{ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
Optab{ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
Optab{ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
Optab{ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
Optab{ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
Optab{ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
Optab{ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0},
Optab{ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0},
Optab{ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0},
Optab{ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
Optab{ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
Optab{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
Optab{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0},
Optab{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0},
Optab{AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0},
Optab{AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
Optab{AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0},
Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
Optab{AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0},
Optab{AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0},
Optab{AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0},
/* store, short offset */
Optab{AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
Optab{AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
Optab{AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
Optab{AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
Optab{AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
Optab{AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
Optab{AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
Optab{AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
Optab{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
/* load, short offset */
Optab{AMOVD, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVW, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVWZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVBZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVBZU, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVB, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
Optab{AMOVBU, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
Optab{AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
Optab{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
Optab{AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
Optab{AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
Optab{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB},
Optab{AMOVD, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
Optab{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
Optab{AMOVWZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
Optab{AMOVBZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
Optab{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, 9, 8, REGSP},
Optab{AMOVD, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVWZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVBZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVBZU, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
Optab{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
Optab{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
/* store, long offset */
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
Optab{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
/* load, long offset */
Optab{AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
Optab{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
Optab{AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
Optab{AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
Optab{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB},
Optab{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
Optab{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
Optab{AMOVWZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
Optab{AMOVBZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
Optab{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 37, 12, REGSP},
Optab{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
Optab{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
Optab{AMOVWZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
Optab{AMOVBZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
Optab{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 37, 12, REGZERO},
Optab{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
Optab{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
Optab{AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
Optab{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
Optab{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
/* load constant */
Optab{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
Optab{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
Optab{AMOVD, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
Optab{AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
Optab{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
Optab{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
Optab{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
Optab{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
Optab{AMOVWZ, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
Optab{AMOVWZ, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
Optab{AMOVWZ, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
Optab{AMOVWZ, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
/* load unsigned/long constants (TO DO: check) */
Optab{AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
Optab{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
Optab{AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
Optab{AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
Optab{AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
Optab{AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
Optab{AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
Optab{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0},
Optab{ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0},
Optab{ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0},
Optab{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
Optab{ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
Optab{ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
Optab{ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0},
Optab{ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0},
Optab{ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0},
Optab{ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0},
Optab{ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0},
Optab{ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
Optab{ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0},
Optab{ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0},
Optab{ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0},
Optab{ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0},
Optab{ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
Optab{AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB},
Optab{AFMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, 8, 4, REGSP},
Optab{AFMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, 8, 4, REGZERO},
Optab{AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB},
Optab{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 36, 8, REGSP},
Optab{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 36, 8, REGZERO},
Optab{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0},
Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
Optab{ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
Optab{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0},
Optab{ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
Optab{ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
Optab{AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
Optab{AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0},
Optab{AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0},
Optab{ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
Optab{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0},
Optab{AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0},
Optab{AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0},
Optab{AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0},
Optab{AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0},
Optab{AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
Optab{AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
Optab{AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
Optab{AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
Optab{AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0},
Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0},
Optab{AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0},
Optab{AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0},
Optab{AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0},
Optab{AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0}, /* mfmsr */
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsrd */
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsr */
/* 64-bit special registers */
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
Optab{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
Optab{AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0},
Optab{AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0},
Optab{AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
/* 32-bit special registers (gloss over sign-extension or not?) */
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
Optab{AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
Optab{AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
Optab{AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
Optab{AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0},
Optab{AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0},
Optab{AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
Optab{AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
Optab{AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0},
Optab{AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
Optab{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
Optab{ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
Optab{ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0},
Optab{ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0},
Optab{ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
Optab{ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
Optab{ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0},
Optab{ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0},
Optab{AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0},
Optab{AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0},
Optab{ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0},
Optab{ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0},
Optab{ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0},
Optab{ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0},
Optab{AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
Optab{AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
Optab{AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
Optab{AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
Optab{AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
Optab{ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0},
Optab{ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0},
Optab{ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
Optab{ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
Optab{ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
Optab{ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0},
Optab{ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
Optab{ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0},
Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0},
Optab{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0},
Optab{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0},
Optab{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0},
Optab{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0},
Optab{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
Optab{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
Optab{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
}
type Oprang struct {
start []Optab
stop []Optab
}
var oprange [ALAST]Oprang
var xcmp [C_NCLASS][C_NCLASS]uint8
func span9(ctxt *obj.Link, cursym *obj.LSym) {
var p *obj.Prog
var q *obj.Prog
var o *Optab
var m int
var bflag int
var c int64
var otxt int64
var out [6]uint32
var i int32
var bp []byte
p = cursym.Text
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
return
}
ctxt.Cursym = cursym
ctxt.Autosize = int32(p.To.Offset + 8)
if oprange[AANDN].start == nil {
buildop(ctxt)
}
c = 0
p.Pc = c
for p = p.Link; p != nil; p = p.Link {
ctxt.Curp = p
p.Pc = c
o = oplook(ctxt, p)
m = int(o.size)
if m == 0 {
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
ctxt.Diag("zero-width instruction\n%v", p)
}
continue
}
c += int64(m)
}
cursym.Size = c
/*
* 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
for bflag != 0 {
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
}
bflag = 0
c = 0
for p = cursym.Text.Link; p != nil; p = p.Link {
p.Pc = c
o = oplook(ctxt, p)
// very large conditional branches
if (o.type_ == 16 || o.type_ == 17) && p.Pcond != nil {
otxt = p.Pcond.Pc - c
if otxt < -(1<<15)+10 || otxt >= (1<<15)-10 {
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
q.As = ABR
q.To.Type = obj.TYPE_BRANCH
q.Pcond = p.Pcond
p.Pcond = q
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
q.As = ABR
q.To.Type = obj.TYPE_BRANCH
q.Pcond = q.Link.Link
//addnop(p->link);
//addnop(p);
bflag = 1
}
}
m = int(o.size)
if m == 0 {
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
ctxt.Diag("zero-width instruction\n%v", p)
}
continue
}
c += int64(m)
}
cursym.Size = c
}
c += -c & (FuncAlign - 1)
cursym.Size = c
/*
* lay out the code, emitting code and data relocations.
*/
if ctxt.Tlsg == nil {
ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
}
obj.Symgrow(ctxt, cursym, cursym.Size)
bp = cursym.P
for p = cursym.Text.Link; p != nil; p = p.Link {
ctxt.Pc = p.Pc
ctxt.Curp = p
o = oplook(ctxt, p)
if int(o.size) > 4*len(out) {
log.Fatalf("out array in span9 is too small, need at least %d for %v", o.size/4, p)
}
asmout(ctxt, p, o, out[:])
for i = 0; i < int32(o.size/4); i++ {
ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
bp = bp[4:]
}
}
}
func isint32(v int64) bool {
return int64(int32(v)) == v
}
func isuint32(v uint64) bool {
return uint64(uint32(v)) == v
}
func aclass(ctxt *obj.Link, a *obj.Addr) int {
var s *obj.LSym
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
}
if REG_C0 <= a.Reg && a.Reg <= REG_C7 || a.Reg == REG_CR {
return C_CREG
}
if REG_SPR0 <= a.Reg && a.Reg <= REG_SPR0+1023 {
switch a.Reg {
case REG_LR:
return C_LR
case REG_XER:
return C_XER
case REG_CTR:
return C_CTR
}
return C_SPR
}
if REG_DCR0 <= a.Reg && a.Reg <= REG_DCR0+1023 {
return C_SPR
}
if a.Reg == REG_FPSCR {
return C_FPSCR
}
if a.Reg == REG_MSR {
return C_MSR
}
return C_GOK
case obj.TYPE_MEM:
switch a.Name {
case obj.NAME_EXTERN,
obj.NAME_STATIC:
if a.Sym == nil {
break
}
ctxt.Instoffset = a.Offset
if a.Sym != nil { // use relocation
return C_ADDR
}
return C_LEXT
case obj.NAME_AUTO:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
return C_SAUTO
}
return C_LAUTO
case obj.NAME_PARAM:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
return C_SAUTO
}
return C_LAUTO
case obj.TYPE_NONE:
ctxt.Instoffset = a.Offset
if ctxt.Instoffset == 0 {
return C_ZOREG
}
if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
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 {
case obj.TYPE_NONE:
ctxt.Instoffset = a.Offset
if a.Reg != 0 {
if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
return C_SACON
}
if isint32(ctxt.Instoffset) {
return C_LACON
}
return C_DACON
}
goto consize
case obj.NAME_EXTERN,
obj.NAME_STATIC:
s = a.Sym
if s == nil {
break
}
if s.Type == obj.SCONST {
ctxt.Instoffset = s.Value + a.Offset
goto consize
}
ctxt.Instoffset = s.Value + a.Offset
/* not sure why this barfs */
return C_LCON
case obj.NAME_AUTO:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
return C_SACON
}
return C_LACON
case obj.NAME_PARAM:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
return C_SACON
}
return C_LACON
}
return C_GOK
consize:
if ctxt.Instoffset >= 0 {
if ctxt.Instoffset == 0 {
return C_ZCON
}
if ctxt.Instoffset <= 0x7fff {
return C_SCON
}
if ctxt.Instoffset <= 0xffff {
return C_ANDCON
}
if ctxt.Instoffset&0xffff == 0 && isuint32(uint64(ctxt.Instoffset)) { /* && (instoffset & (1<<31)) == 0) */
return C_UCON
}
if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
return C_LCON
}
return C_DCON
}
if ctxt.Instoffset >= -0x8000 {
return C_ADDCON
}
if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) {
return C_UCON
}
if isint32(ctxt.Instoffset) {
return C_LCON
}
return C_DCON
case obj.TYPE_BRANCH:
return C_SBRA
}
return C_GOK
}
func prasm(p *obj.Prog) {
fmt.Printf("%v\n", p)
}
func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
var a1 int
var a2 int
var a3 int
var a4 int
var r int
var c1 []byte
var c3 []byte
var c4 []byte
var o []Optab
var e []Optab
a1 = int(p.Optab)
if a1 != 0 {
return &optab[a1-1:][0]
}
a1 = int(p.From.Class)
if a1 == 0 {
a1 = aclass(ctxt, &p.From) + 1
p.From.Class = int8(a1)
}
a1--
a3 = int(p.From3.Class)
if a3 == 0 {
a3 = aclass(ctxt, &p.From3) + 1
p.From3.Class = int8(a3)
}
a3--
a4 = int(p.To.Class)
if a4 == 0 {
a4 = aclass(ctxt, &p.To) + 1
p.To.Class = int8(a4)
}
a4--
a2 = C_NONE
if p.Reg != 0 {
a2 = C_REG
}
//print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4);
r = int(p.As)
o = oprange[r].start
if o == nil {
o = oprange[r].stop /* just generate an error */
}
e = oprange[r].stop
c1 = xcmp[a1][:]
c3 = xcmp[a3][:]
c4 = xcmp[a4][:]
for ; -cap(o) < -cap(e); o = o[1:] {
if int(o[0].a2) == a2 {
if c1[o[0].a1] != 0 {
if c3[o[0].a3] != 0 {
if c4[o[0].a4] != 0 {
p.Optab = uint16((-cap(o) + cap(optab)) + 1)
return &o[0]
}
}
}
}
}
ctxt.Diag("illegal combination %v %v %v %v %v", Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4))
prasm(p)
if o == nil {
o = optab
}
return &o[0]
}
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
}
case C_ADDCON:
if b == C_ZCON || b == C_SCON {
return true
}
case C_ANDCON:
if b == C_ZCON || b == C_SCON {
return true
}
case C_SPR:
if b == C_LR || b == C_XER || b == C_CTR {
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
}
case C_ANY:
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 {
var p1 *Optab
var p2 *Optab
var n int
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
}
n = int(p1.a4) - int(p2.a4)
if n != 0 {
return n < 0
}
return false
}
func buildop(ctxt *obj.Link) {
var i int
var n int
var r int
for i = 0; i < C_NCLASS; i++ {
for n = 0; n < C_NCLASS; n++ {
if cmp(n, i) {
xcmp[i][n] = 1
}
}
}
for n = 0; optab[n].as != obj.AXXX; n++ {
}
sort.Sort(ocmp(optab[:n]))
for i = 0; i < n; i++ {
r = int(optab[i].as)
oprange[r].start = optab[i:]
for int(optab[i].as) == r {
i++
}
oprange[r].stop = optab[i:]
i--
switch r {
default:
ctxt.Diag("unknown op in build: %v", Aconv(r))
log.Fatalf("bad code")
case ADCBF: /* unary indexed: op (b+a); op (b) */
oprange[ADCBI] = oprange[r]
oprange[ADCBST] = oprange[r]
oprange[ADCBT] = oprange[r]
oprange[ADCBTST] = oprange[r]
oprange[ADCBZ] = oprange[r]
oprange[AICBI] = oprange[r]
case AECOWX: /* indexed store: op s,(b+a); op s,(b) */
oprange[ASTWCCC] = oprange[r]
oprange[ASTDCCC] = oprange[r]
case AREM: /* macro */
oprange[AREMCC] = oprange[r]
oprange[AREMV] = oprange[r]
oprange[AREMVCC] = oprange[r]
case AREMU:
oprange[AREMU] = oprange[r]
oprange[AREMUCC] = oprange[r]
oprange[AREMUV] = oprange[r]
oprange[AREMUVCC] = oprange[r]
case AREMD:
oprange[AREMDCC] = oprange[r]
oprange[AREMDV] = oprange[r]
oprange[AREMDVCC] = oprange[r]
case AREMDU:
oprange[AREMDU] = oprange[r]
oprange[AREMDUCC] = oprange[r]
oprange[AREMDUV] = oprange[r]
oprange[AREMDUVCC] = oprange[r]
case ADIVW: /* op Rb[,Ra],Rd */
oprange[AMULHW] = oprange[r]
oprange[AMULHWCC] = oprange[r]
oprange[AMULHWU] = oprange[r]
oprange[AMULHWUCC] = oprange[r]
oprange[AMULLWCC] = oprange[r]
oprange[AMULLWVCC] = oprange[r]
oprange[AMULLWV] = oprange[r]
oprange[ADIVWCC] = oprange[r]
oprange[ADIVWV] = oprange[r]
oprange[ADIVWVCC] = oprange[r]
oprange[ADIVWU] = oprange[r]
oprange[ADIVWUCC] = oprange[r]
oprange[ADIVWUV] = oprange[r]
oprange[ADIVWUVCC] = oprange[r]
oprange[AADDCC] = oprange[r]
oprange[AADDCV] = oprange[r]
oprange[AADDCVCC] = oprange[r]
oprange[AADDV] = oprange[r]
oprange[AADDVCC] = oprange[r]
oprange[AADDE] = oprange[r]
oprange[AADDECC] = oprange[r]
oprange[AADDEV] = oprange[r]
oprange[AADDEVCC] = oprange[r]
oprange[ACRAND] = oprange[r]
oprange[ACRANDN] = oprange[r]
oprange[ACREQV] = oprange[r]
oprange[ACRNAND] = oprange[r]
oprange[ACRNOR] = oprange[r]
oprange[ACROR] = oprange[r]
oprange[ACRORN] = oprange[r]
oprange[ACRXOR] = oprange[r]
oprange[AMULHD] = oprange[r]
oprange[AMULHDCC] = oprange[r]
oprange[AMULHDU] = oprange[r]
oprange[AMULHDUCC] = oprange[r]
oprange[AMULLD] = oprange[r]
oprange[AMULLDCC] = oprange[r]
oprange[AMULLDVCC] = oprange[r]
oprange[AMULLDV] = oprange[r]
oprange[ADIVD] = oprange[r]
oprange[ADIVDCC] = oprange[r]
oprange[ADIVDVCC] = oprange[r]
oprange[ADIVDV] = oprange[r]
oprange[ADIVDU] = oprange[r]
oprange[ADIVDUCC] = oprange[r]
oprange[ADIVDUVCC] = oprange[r]
oprange[ADIVDUCC] = oprange[r]
case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
oprange[AMOVH] = oprange[r]
oprange[AMOVHZ] = oprange[r]
case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
oprange[AMOVHU] = oprange[r]
oprange[AMOVHZU] = oprange[r]
oprange[AMOVWU] = oprange[r]
oprange[AMOVWZU] = oprange[r]
oprange[AMOVDU] = oprange[r]
oprange[AMOVMW] = oprange[r]
case AAND: /* logical op Rb,Rs,Ra; no literal */
oprange[AANDN] = oprange[r]
oprange[AANDNCC] = oprange[r]
oprange[AEQV] = oprange[r]
oprange[AEQVCC] = oprange[r]
oprange[ANAND] = oprange[r]
oprange[ANANDCC] = oprange[r]
oprange[ANOR] = oprange[r]
oprange[ANORCC] = oprange[r]
oprange[AORCC] = oprange[r]
oprange[AORN] = oprange[r]
oprange[AORNCC] = oprange[r]
oprange[AXORCC] = oprange[r]
case AADDME: /* op Ra, Rd */
oprange[AADDMECC] = oprange[r]
oprange[AADDMEV] = oprange[r]
oprange[AADDMEVCC] = oprange[r]
oprange[AADDZE] = oprange[r]
oprange[AADDZECC] = oprange[r]
oprange[AADDZEV] = oprange[r]
oprange[AADDZEVCC] = oprange[r]
oprange[ASUBME] = oprange[r]
oprange[ASUBMECC] = oprange[r]
oprange[ASUBMEV] = oprange[r]
oprange[ASUBMEVCC] = oprange[r]
oprange[ASUBZE] = oprange[r]
oprange[ASUBZECC] = oprange[r]
oprange[ASUBZEV] = oprange[r]
oprange[ASUBZEVCC] = oprange[r]
case AADDC:
oprange[AADDCCC] = oprange[r]
case ABEQ:
oprange[ABGE] = oprange[r]
oprange[ABGT] = oprange[r]
oprange[ABLE] = oprange[r]
oprange[ABLT] = oprange[r]
oprange[ABNE] = oprange[r]
oprange[ABVC] = oprange[r]
oprange[ABVS] = oprange[r]
case ABR:
oprange[ABL] = oprange[r]
case ABC:
oprange[ABCL] = oprange[r]
case AEXTSB: /* op Rs, Ra */
oprange[AEXTSBCC] = oprange[r]
oprange[AEXTSH] = oprange[r]
oprange[AEXTSHCC] = oprange[r]
oprange[ACNTLZW] = oprange[r]
oprange[ACNTLZWCC] = oprange[r]
oprange[ACNTLZD] = oprange[r]
oprange[AEXTSW] = oprange[r]
oprange[AEXTSWCC] = oprange[r]
oprange[ACNTLZDCC] = oprange[r]
case AFABS: /* fop [s,]d */
oprange[AFABSCC] = oprange[r]
oprange[AFNABS] = oprange[r]
oprange[AFNABSCC] = oprange[r]
oprange[AFNEG] = oprange[r]
oprange[AFNEGCC] = oprange[r]
oprange[AFRSP] = oprange[r]
oprange[AFRSPCC] = oprange[r]
oprange[AFCTIW] = oprange[r]
oprange[AFCTIWCC] = oprange[r]
oprange[AFCTIWZ] = oprange[r]
oprange[AFCTIWZCC] = oprange[r]
oprange[AFCTID] = oprange[r]
oprange[AFCTIDCC] = oprange[r]
oprange[AFCTIDZ] = oprange[r]
oprange[AFCTIDZCC] = oprange[r]
oprange[AFCFID] = oprange[r]
oprange[AFCFIDCC] = oprange[r]
oprange[AFRES] = oprange[r]
oprange[AFRESCC] = oprange[r]
oprange[AFRSQRTE] = oprange[r]
oprange[AFRSQRTECC] = oprange[r]
oprange[AFSQRT] = oprange[r]
oprange[AFSQRTCC] = oprange[r]
oprange[AFSQRTS] = oprange[r]
oprange[AFSQRTSCC] = oprange[r]
case AFADD:
oprange[AFADDS] = oprange[r]
oprange[AFADDCC] = oprange[r]
oprange[AFADDSCC] = oprange[r]
oprange[AFDIV] = oprange[r]
oprange[AFDIVS] = oprange[r]
oprange[AFDIVCC] = oprange[r]
oprange[AFDIVSCC] = oprange[r]
oprange[AFSUB] = oprange[r]
oprange[AFSUBS] = oprange[r]
oprange[AFSUBCC] = oprange[r]
oprange[AFSUBSCC] = oprange[r]
case AFMADD:
oprange[AFMADDCC] = oprange[r]
oprange[AFMADDS] = oprange[r]
oprange[AFMADDSCC] = oprange[r]
oprange[AFMSUB] = oprange[r]
oprange[AFMSUBCC] = oprange[r]
oprange[AFMSUBS] = oprange[r]
oprange[AFMSUBSCC] = oprange[r]
oprange[AFNMADD] = oprange[r]
oprange[AFNMADDCC] = oprange[r]
oprange[AFNMADDS] = oprange[r]
oprange[AFNMADDSCC] = oprange[r]
oprange[AFNMSUB] = oprange[r]
oprange[AFNMSUBCC] = oprange[r]
oprange[AFNMSUBS] = oprange[r]
oprange[AFNMSUBSCC] = oprange[r]
oprange[AFSEL] = oprange[r]
oprange[AFSELCC] = oprange[r]
case AFMUL:
oprange[AFMULS] = oprange[r]
oprange[AFMULCC] = oprange[r]
oprange[AFMULSCC] = oprange[r]
case AFCMPO:
oprange[AFCMPU] = oprange[r]
case AMTFSB0:
oprange[AMTFSB0CC] = oprange[r]
oprange[AMTFSB1] = oprange[r]
oprange[AMTFSB1CC] = oprange[r]
case ANEG: /* op [Ra,] Rd */
oprange[ANEGCC] = oprange[r]
oprange[ANEGV] = oprange[r]
oprange[ANEGVCC] = oprange[r]
case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
oprange[AXOR] = oprange[r]
case ASLW:
oprange[ASLWCC] = oprange[r]
oprange[ASRW] = oprange[r]
oprange[ASRWCC] = oprange[r]
case ASLD:
oprange[ASLDCC] = oprange[r]
oprange[ASRD] = oprange[r]
oprange[ASRDCC] = oprange[r]
case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
oprange[ASRAWCC] = oprange[r]
case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
oprange[ASRADCC] = oprange[r]
case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */
oprange[ASUB] = oprange[r]
oprange[ASUBCC] = oprange[r]
oprange[ASUBV] = oprange[r]
oprange[ASUBVCC] = oprange[r]
oprange[ASUBCCC] = oprange[r]
oprange[ASUBCV] = oprange[r]
oprange[ASUBCVCC] = oprange[r]
oprange[ASUBE] = oprange[r]
oprange[ASUBECC] = oprange[r]
oprange[ASUBEV] = oprange[r]
oprange[ASUBEVCC] = oprange[r]
case ASYNC:
oprange[AISYNC] = oprange[r]
oprange[APTESYNC] = oprange[r]
oprange[ATLBSYNC] = oprange[r]
case ARLWMI:
oprange[ARLWMICC] = oprange[r]
oprange[ARLWNM] = oprange[r]
oprange[ARLWNMCC] = oprange[r]
case ARLDMI:
oprange[ARLDMICC] = oprange[r]
case ARLDC:
oprange[ARLDCCC] = oprange[r]
case ARLDCL:
oprange[ARLDCR] = oprange[r]
oprange[ARLDCLCC] = oprange[r]
oprange[ARLDCRCC] = oprange[r]
case AFMOVD:
oprange[AFMOVDCC] = oprange[r]
oprange[AFMOVDU] = oprange[r]
oprange[AFMOVS] = oprange[r]
oprange[AFMOVSU] = oprange[r]
case AECIWX:
oprange[ALWAR] = oprange[r]
oprange[ALDAR] = oprange[r]
case ASYSCALL: /* just the op; flow of control */
oprange[ARFI] = oprange[r]
oprange[ARFCI] = oprange[r]
oprange[ARFID] = oprange[r]
oprange[AHRFID] = oprange[r]
case AMOVHBR:
oprange[AMOVWBR] = oprange[r]
case ASLBMFEE:
oprange[ASLBMFEV] = oprange[r]
case ATW:
oprange[ATD] = oprange[r]
case ATLBIE:
oprange[ASLBIE] = oprange[r]
oprange[ATLBIEL] = oprange[r]
case AEIEIO:
oprange[ASLBIA] = oprange[r]
case ACMP:
oprange[ACMPW] = oprange[r]
case ACMPU:
oprange[ACMPWU] = oprange[r]
case AADD,
AANDCC, /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
ALSW,
AMOVW,
/* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
AMOVWZ, /* load/store/move word with zero extension; move 32-bit literals */
AMOVD, /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
AMOVB, /* macro: move byte with sign extension */
AMOVBU, /* macro: move byte with sign extension & update */
AMOVFL,
AMULLW,
/* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
ASUBC, /* op r1,$s,r3; op r1[,r2],r3 */
ASTSW,
ASLBMTE,
AWORD,
ADWORD,
obj.ANOP,
obj.ATEXT,
obj.AUNDEF,
obj.AUSEFIELD,
obj.AFUNCDATA,
obj.APCDATA,
obj.ADUFFZERO,
obj.ADUFFCOPY:
break
}
}
}
func OPVCC(o uint32, xo uint32, oe uint32, rc uint32) uint32 {
return o<<26 | xo<<1 | oe<<10 | rc&1
}
func OPCC(o uint32, xo uint32, rc uint32) uint32 {
return OPVCC(o, xo, 0, rc)
}
func OP(o uint32, xo uint32) uint32 {
return OPVCC(o, xo, 0, 0)
}
/* the order is dest, a/s, b/imm for both arithmetic and logical operations */
func AOP_RRR(op uint32, d uint32, a uint32, b uint32) uint32 {
return op | (d&31)<<21 | (a&31)<<16 | (b&31)<<11
}
func AOP_IRR(op uint32, d uint32, a uint32, simm uint32) uint32 {
return op | (d&31)<<21 | (a&31)<<16 | simm&0xFFFF
}
func LOP_RRR(op uint32, a uint32, s uint32, b uint32) uint32 {
return op | (s&31)<<21 | (a&31)<<16 | (b&31)<<11
}
func LOP_IRR(op uint32, a uint32, s uint32, uimm uint32) uint32 {
return op | (s&31)<<21 | (a&31)<<16 | uimm&0xFFFF
}
func OP_BR(op uint32, li uint32, aa uint32) uint32 {
return op | li&0x03FFFFFC | aa<<1
}
func OP_BC(op uint32, bo uint32, bi uint32, bd uint32, aa uint32) uint32 {
return op | (bo&0x1F)<<21 | (bi&0x1F)<<16 | bd&0xFFFC | aa<<1
}
func OP_BCR(op uint32, bo uint32, bi uint32) uint32 {
return op | (bo&0x1F)<<21 | (bi&0x1F)<<16
}
func OP_RLW(op uint32, a uint32, s uint32, sh uint32, mb uint32, me uint32) uint32 {
return op | (s&31)<<21 | (a&31)<<16 | (sh&31)<<11 | (mb&31)<<6 | (me&31)<<1
}
const (
OP_ADD = 31<<26 | 266<<1 | 0<<10 | 0
OP_ADDI = 14<<26 | 0<<1 | 0<<10 | 0
OP_ADDIS = 15<<26 | 0<<1 | 0<<10 | 0
OP_ANDI = 28<<26 | 0<<1 | 0<<10 | 0
OP_EXTSB = 31<<26 | 954<<1 | 0<<10 | 0
OP_EXTSH = 31<<26 | 922<<1 | 0<<10 | 0
OP_EXTSW = 31<<26 | 986<<1 | 0<<10 | 0
OP_MCRF = 19<<26 | 0<<1 | 0<<10 | 0
OP_MCRFS = 63<<26 | 64<<1 | 0<<10 | 0
OP_MCRXR = 31<<26 | 512<<1 | 0<<10 | 0
OP_MFCR = 31<<26 | 19<<1 | 0<<10 | 0
OP_MFFS = 63<<26 | 583<<1 | 0<<10 | 0
OP_MFMSR = 31<<26 | 83<<1 | 0<<10 | 0
OP_MFSPR = 31<<26 | 339<<1 | 0<<10 | 0
OP_MFSR = 31<<26 | 595<<1 | 0<<10 | 0
OP_MFSRIN = 31<<26 | 659<<1 | 0<<10 | 0
OP_MTCRF = 31<<26 | 144<<1 | 0<<10 | 0
OP_MTFSF = 63<<26 | 711<<1 | 0<<10 | 0
OP_MTFSFI = 63<<26 | 134<<1 | 0<<10 | 0
OP_MTMSR = 31<<26 | 146<<1 | 0<<10 | 0
OP_MTMSRD = 31<<26 | 178<<1 | 0<<10 | 0
OP_MTSPR = 31<<26 | 467<<1 | 0<<10 | 0
OP_MTSR = 31<<26 | 210<<1 | 0<<10 | 0
OP_MTSRIN = 31<<26 | 242<<1 | 0<<10 | 0
OP_MULLW = 31<<26 | 235<<1 | 0<<10 | 0
OP_MULLD = 31<<26 | 233<<1 | 0<<10 | 0
OP_OR = 31<<26 | 444<<1 | 0<<10 | 0
OP_ORI = 24<<26 | 0<<1 | 0<<10 | 0
OP_ORIS = 25<<26 | 0<<1 | 0<<10 | 0
OP_RLWINM = 21<<26 | 0<<1 | 0<<10 | 0
OP_SUBF = 31<<26 | 40<<1 | 0<<10 | 0
OP_RLDIC = 30<<26 | 4<<1 | 0<<10 | 0
OP_RLDICR = 30<<26 | 2<<1 | 0<<10 | 0
OP_RLDICL = 30<<26 | 0<<1 | 0<<10 | 0
)
func oclass(a *obj.Addr) int {
return int(a.Class) - 1
}
// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
func addaddrreloc(ctxt *obj.Link, s *obj.LSym, o1 *uint32, o2 *uint32) {
var rel *obj.Reloc
rel = obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 8
rel.Sym = s
rel.Add = int64(uint64(*o1)<<32 | uint64(uint32(*o2)))
rel.Type = obj.R_ADDRPOWER
}
/*
* 32-bit masks
*/
func getmask(m []byte, v uint32) bool {
var i int
m[1] = 0
m[0] = m[1]
if v != ^uint32(0) && v&(1<<31) != 0 && v&1 != 0 { /* MB > ME */
if getmask(m, ^v) {
i = int(m[0])
m[0] = m[1] + 1
m[1] = byte(i - 1)
return true
}
return false
}
for i = 0; i < 32; i++ {
if v&(1<<uint(31-i)) != 0 {
m[0] = byte(i)
for {
m[1] = byte(i)
i++
if i >= 32 || v&(1<<uint(31-i)) == 0 {
break
}
}
for ; i < 32; i++ {
if v&(1<<uint(31-i)) != 0 {
return false
}
}
return true
}
}
return false
}
func maskgen(ctxt *obj.Link, p *obj.Prog, m []byte, v uint32) {
if !getmask(m, v) {
ctxt.Diag("cannot generate mask #%x\n%v", v, p)
}
}
/*
* 64-bit masks (rldic etc)
*/
func getmask64(m []byte, v uint64) bool {
var i int
m[1] = 0
m[0] = m[1]
for i = 0; i < 64; i++ {
if v&(uint64(1)<<uint(63-i)) != 0 {
m[0] = byte(i)
for {
m[1] = byte(i)
i++
if i >= 64 || v&(uint64(1)<<uint(63-i)) == 0 {
break
}
}
for ; i < 64; i++ {
if v&(uint64(1)<<uint(63-i)) != 0 {
return false
}
}
return true
}
}
return false
}
func maskgen64(ctxt *obj.Link, p *obj.Prog, m []byte, v uint64) {
if !getmask64(m, v) {
ctxt.Diag("cannot generate mask #%x\n%v", v, p)
}
}
func loadu32(r int, d int64) uint32 {
var v int32
v = int32(d >> 16)
if isuint32(uint64(d)) {
return LOP_IRR(OP_ORIS, uint32(r), REGZERO, uint32(v))
}
return AOP_IRR(OP_ADDIS, uint32(r), REGZERO, uint32(v))
}
func high16adjusted(d int32) uint16 {
if d&0x8000 != 0 {
return uint16((d >> 16) + 1)
}
return uint16(d >> 16)
}
func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
var o1 uint32
var o2 uint32
var o3 uint32
var o4 uint32
var o5 uint32
var v int32
var t int32
var d int64
var r int
var a int
var mask [2]uint8
var rel *obj.Reloc
o1 = 0
o2 = 0
o3 = 0
o4 = 0
o5 = 0
//print("%P => case %d\n", p, o->type);
switch o.type_ {
default:
ctxt.Diag("unknown type %d", o.type_)
prasm(p)
case 0: /* pseudo ops */
break
case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */
if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST {
v = regoff(ctxt, &p.From)
if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 {
//nerrors--;
ctxt.Diag("literal operation on R0\n%v", p)
}
o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
break
}
o1 = LOP_RRR(OP_OR, uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg))
case 2: /* int/cr/fp op Rb,[Ra],Rd */
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
d = vregoff(ctxt, &p.From)
v = int32(d)
r = int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 && (r != 0 || v != 0) {
ctxt.Diag("literal operation on R0\n%v", p)
}
a = OP_ADDI
if o.a1 == C_UCON {
if d&0xffff != 0 {
log.Fatalf("invalid handling of %v", p)
}
v >>= 16
if r == REGZERO && isuint32(uint64(d)) {
o1 = LOP_IRR(OP_ORIS, uint32(p.To.Reg), REGZERO, uint32(v))
break
}
a = OP_ADDIS
} else {
if int64(int16(d)) != d {
log.Fatalf("invalid handling of %v", p)
}
}
o1 = AOP_IRR(uint32(a), uint32(p.To.Reg), uint32(r), uint32(v))
case 4: /* add/mul $scon,[r1],r2 */
v = regoff(ctxt, &p.From)
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
if r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0 {
ctxt.Diag("literal operation on R0\n%v", p)
}
if int32(int16(v)) != v {
log.Fatalf("mishandled instruction %v", p)
}
o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
case 5: /* syscall */
o1 = uint32(oprrr(ctxt, int(p.As)))
case 6: /* logical op Rb,[Rs,]Ra; no literal */
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
case 7: /* mov r, soreg ==> stw o(r) */
r = int(p.To.Reg)
if r == 0 {
r = int(o.param)
}
v = regoff(ctxt, &p.To)
if p.To.Type == obj.TYPE_MEM && p.Reg != 0 {
if v != 0 {
ctxt.Diag("illegal indexed instruction\n%v", p)
}
o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.Reg), uint32(r))
} else {
if int32(int16(v)) != v {
log.Fatalf("mishandled instruction %v", p)
}
o1 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), uint32(r), uint32(v))
}
case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
r = int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
v = regoff(ctxt, &p.From)
if p.From.Type == obj.TYPE_MEM && p.Reg != 0 {
if v != 0 {
ctxt.Diag("illegal indexed instruction\n%v", p)
}
o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.Reg), uint32(r))
} else {
if int32(int16(v)) != v {
log.Fatalf("mishandled instruction %v", p)
}
o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
}
case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
r = int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
v = regoff(ctxt, &p.From)
if p.From.Type == obj.TYPE_MEM && p.Reg != 0 {
if v != 0 {
ctxt.Diag("illegal indexed instruction\n%v", p)
}
o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.Reg), uint32(r))
} else {
o1 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
}
o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(r))
case 11: /* br/bl lbra */
v = 0
if p.Pcond != nil {
v = int32(p.Pcond.Pc - p.Pc)
if v&03 != 0 {
ctxt.Diag("odd branch target address\n%v", p)
v &^= 03
}
if v < -(1<<25) || v >= 1<<24 {
ctxt.Diag("branch too far\n%v", p)
}
}
o1 = OP_BR(uint32(opirr(ctxt, int(p.As))), uint32(v), 0)
if p.To.Sym != nil {
rel = obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 4
rel.Sym = p.To.Sym
v += int32(p.To.Offset)
if v&03 != 0 {
ctxt.Diag("odd branch target address\n%v", p)
v &^= 03
}
rel.Add = int64(v)
rel.Type = obj.R_CALLPOWER
}
case 12: /* movb r,r (extsb); movw r,r (extsw) */
if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST {
v = regoff(ctxt, &p.From)
if r0iszero != 0 /*TypeKind(100016)*/ && v != 0 {
ctxt.Diag("literal operation on R0\n%v", p)
}
o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(v))
break
}
if p.As == AMOVW {
o1 = LOP_RRR(OP_EXTSW, uint32(p.To.Reg), uint32(p.From.Reg), 0)
} else {
o1 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.From.Reg), 0)
}
case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
if p.As == AMOVBZ {
o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 24, 31)
} else if p.As == AMOVH {
o1 = LOP_RRR(OP_EXTSH, uint32(p.To.Reg), uint32(p.From.Reg), 0)
} else if p.As == AMOVHZ {
o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.From.Reg), 0, 16, 31)
} else if p.As == AMOVWZ {
o1 = OP_RLW(OP_RLDIC, uint32(p.To.Reg), uint32(p.From.Reg), 0, 0, 0) | 1<<5 /* MB=32 */
} else {
ctxt.Diag("internal: bad mov[bhw]z\n%v", p)
}
case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
d = vregoff(ctxt, &p.From3)
maskgen64(ctxt, p, mask[:], uint64(d))
switch p.As {
case ARLDCL,
ARLDCLCC:
a = int(mask[0]) /* MB */
if mask[1] != 63 {
ctxt.Diag("invalid mask for rotate: %x (end != bit 63)\n%v", uint64(d), p)
}
case ARLDCR,
ARLDCRCC:
a = int(mask[1]) /* ME */
if mask[0] != 0 {
ctxt.Diag("invalid mask for rotate: %x (start != 0)\n%v", uint64(d), p)
}
default:
ctxt.Diag("unexpected op in rldc case\n%v", p)
a = 0
}
o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
o1 |= (uint32(a) & 31) << 6
if a&0x20 != 0 {
o1 |= 1 << 5 /* mb[5] is top bit */
}
case 17, /* bc bo,bi,lbra (same for now) */
16: /* bc bo,bi,sbra */
a = 0
if p.From.Type == obj.TYPE_CONST {
a = int(regoff(ctxt, &p.From))
}
r = int(p.Reg)
if r == 0 {
r = 0
}
v = 0
if p.Pcond != nil {
v = int32(p.Pcond.Pc - p.Pc)
}
if v&03 != 0 {
ctxt.Diag("odd branch target address\n%v", p)
v &^= 03
}
if v < -(1<<16) || v >= 1<<15 {
ctxt.Diag("branch too far\n%v", p)
}
o1 = OP_BC(uint32(opirr(ctxt, int(p.As))), uint32(a), uint32(r), uint32(v), 0)
case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */
if p.As == ABC || p.As == ABCL {
v = regoff(ctxt, &p.To) & 31
} else {
v = 20 /* unconditional */
}
r = int(p.Reg)
if r == 0 {
r = 0
}
o1 = AOP_RRR(OP_MTSPR, uint32(p.To.Reg), 0, 0) | (REG_LR&0x1f)<<16 | ((REG_LR>>5)&0x1f)<<11
o2 = OPVCC(19, 16, 0, 0)
if p.As == ABL || p.As == ABCL {
o2 |= 1
}
o2 = OP_BCR(o2, uint32(v), uint32(r))
case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
if p.As == ABC || p.As == ABCL {
v = regoff(ctxt, &p.From) & 31
} else {
v = 20 /* unconditional */
}
r = int(p.Reg)
if r == 0 {
r = 0
}
switch oclass(&p.To) {
case C_CTR:
o1 = OPVCC(19, 528, 0, 0)
case C_LR:
o1 = OPVCC(19, 16, 0, 0)
default:
ctxt.Diag("bad optab entry (18): %d\n%v", p.To.Class, p)
v = 0
}
if p.As == ABL || p.As == ABCL {
o1 |= 1
}
o1 = OP_BCR(o1, uint32(v), uint32(r))
case 19: /* mov $lcon,r ==> cau+or */
d = vregoff(ctxt, &p.From)
if p.From.Sym == nil {
o1 = loadu32(int(p.To.Reg), d)
o2 = LOP_IRR(OP_ORI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(int32(d)))
} else {
o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(int32(d))))
o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(d))
addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
}
//if(dlm) reloc(&p->from, p->pc, 0);
case 20: /* add $ucon,,r */
v = regoff(ctxt, &p.From)
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
if p.As == AADD && (r0iszero == 0 /*TypeKind(100016)*/ && p.Reg == 0 || r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0) {
ctxt.Diag("literal operation on R0\n%v", p)
}
o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As)+ALAST)), uint32(p.To.Reg), uint32(r), uint32(v)>>16)
case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */
if p.To.Reg == REGTMP || p.Reg == REGTMP {
ctxt.Diag("cant synthesize large constant\n%v", p)
}
d = vregoff(ctxt, &p.From)
o1 = loadu32(REGTMP, d)
o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r))
if p.From.Sym != nil {
ctxt.Diag("%v is not supported", p)
}
//if(dlm) reloc(&p->from, p->pc, 0);
case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */
if p.To.Reg == REGTMP || p.Reg == REGTMP {
ctxt.Diag("cant synthesize large constant\n%v", p)
}
d = vregoff(ctxt, &p.From)
o1 = loadu32(REGTMP, d)
o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(int32(d)))
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o3 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(r))
if p.From.Sym != nil {
ctxt.Diag("%v is not supported", p)
}
//if(dlm) reloc(&p->from, p->pc, 0);
/*24*/
case 25:
/* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
v = regoff(ctxt, &p.From)
if v < 0 {
v = 0
} else if v > 63 {
v = 63
}
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
switch p.As {
case ASLD,
ASLDCC:
a = int(63 - v)
o1 = OP_RLDICR
case ASRD,
ASRDCC:
a = int(v)
v = 64 - v
o1 = OP_RLDICL
default:
ctxt.Diag("unexpected op in sldi case\n%v", p)
a = 0
o1 = 0
}
o1 = AOP_RRR(o1, uint32(r), uint32(p.To.Reg), (uint32(v) & 0x1F))
o1 |= (uint32(a) & 31) << 6
if v&0x20 != 0 {
o1 |= 1 << 1
}
if a&0x20 != 0 {
o1 |= 1 << 5 /* mb[5] is top bit */
}
if p.As == ASLDCC || p.As == ASRDCC {
o1 |= 1 /* Rc */
}
case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */
if p.To.Reg == REGTMP {
ctxt.Diag("can't synthesize large constant\n%v", p)
}
v = regoff(ctxt, &p.From)
r = int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(v))
case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
v = regoff(ctxt, &p.From3)
r = int(p.From.Reg)
o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
case 28: /* subc r1,$lcon,r2 ==> cau+or+subfc */
if p.To.Reg == REGTMP || p.From.Reg == REGTMP {
ctxt.Diag("can't synthesize large constant\n%v", p)
}
v = regoff(ctxt, &p.From3)
o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(v)>>16)
o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(v))
o3 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), REGTMP)
if p.From.Sym != nil {
ctxt.Diag("%v is not supported", p)
}
//if(dlm) reloc(&p->from3, p->pc, 0);
case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
v = regoff(ctxt, &p.From)
d = vregoff(ctxt, &p.From3)
maskgen64(ctxt, p, mask[:], uint64(d))
switch p.As {
case ARLDC,
ARLDCCC:
a = int(mask[0]) /* MB */
if int32(mask[1]) != (63 - v) {
ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
}
case ARLDCL,
ARLDCLCC:
a = int(mask[0]) /* MB */
if mask[1] != 63 {
ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
}
case ARLDCR,
ARLDCRCC:
a = int(mask[1]) /* ME */
if mask[0] != 0 {
ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
}
default:
ctxt.Diag("unexpected op in rldic case\n%v", p)
a = 0
}
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
o1 |= (uint32(a) & 31) << 6
if v&0x20 != 0 {
o1 |= 1 << 1
}
if a&0x20 != 0 {
o1 |= 1 << 5 /* mb[5] is top bit */
}
case 30: /* rldimi $sh,s,$mask,a */
v = regoff(ctxt, &p.From)
d = vregoff(ctxt, &p.From3)
maskgen64(ctxt, p, mask[:], uint64(d))
if int32(mask[1]) != (63 - v) {
ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
}
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
o1 |= (uint32(mask[0]) & 31) << 6
if v&0x20 != 0 {
o1 |= 1 << 1
}
if mask[0]&0x20 != 0 {
o1 |= 1 << 5 /* mb[5] is top bit */
}
case 31: /* dword */
d = vregoff(ctxt, &p.From)
if ctxt.Arch.Endian == obj.BigEndian {
o1 = uint32(d >> 32)
o2 = uint32(d)
} else {
o1 = uint32(d)
o2 = uint32(d >> 32)
}
if p.From.Sym != nil {
rel = obj.Addrel(ctxt.Cursym)
rel.Off = int32(ctxt.Pc)
rel.Siz = 8
rel.Sym = p.From.Sym
rel.Add = p.From.Offset
rel.Type = obj.R_ADDR
o2 = 0
o1 = o2
}
case 32: /* fmul frc,fra,frd */
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0) | (uint32(p.From.Reg)&31)<<6
case 33: /* fabs [frb,]frd; fmr. frb,frd */
r = int(p.From.Reg)
if oclass(&p.From) == C_NONE {
r = int(p.To.Reg)
}
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(r))
case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) | (uint32(p.From3.Reg)&31)<<6
case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
v = regoff(ctxt, &p.To)
r = int(p.To.Reg)
if r == 0 {
r = int(o.param)
}
o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
v = regoff(ctxt, &p.From)
r = int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
v = regoff(ctxt, &p.From)
r = int(p.From.Reg)
if r == 0 {
r = int(o.param)
}
o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
case 40: /* word */
o1 = uint32(regoff(ctxt, &p.From))
case 41: /* stswi */
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(regoff(ctxt, &p.From3))&0x7F)<<11
case 42: /* lswi */
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(regoff(ctxt, &p.From3))&0x7F)<<11
case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
r = int(p.Reg)
if r == 0 {
r = 0
}
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, uint32(r), uint32(p.From.Reg))
case 44: /* indexed store */
r = int(p.Reg)
if r == 0 {
r = 0
}
o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
case 45: /* indexed load */
r = int(p.Reg)
if r == 0 {
r = 0
}
o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(p.From.Reg))
case 46: /* plain op */
o1 = uint32(oprrr(ctxt, int(p.As)))
case 47: /* op Ra, Rd; also op [Ra,] Rd */
r = int(p.From.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
case 48: /* op Rs, Ra */
r = int(p.From.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = LOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), 0)
case 49: /* op Rb; op $n, Rb */
if p.From.Type != obj.TYPE_REG { /* tlbie $L, rB */
v = regoff(ctxt, &p.From) & 1
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.To.Reg)) | uint32(v)<<21
} else {
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), 0, 0, uint32(p.From.Reg))
}
case 50: /* rem[u] r1[,r2],r3 */
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
v = oprrr(ctxt, int(p.As))
t = v & (1<<10 | 1) /* OE|Rc */
o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg))
o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, uint32(p.From.Reg))
o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r))
if p.As == AREMU {
o4 = o3
/* Clear top 32 bits */
o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | 1<<5
}
case 51: /* remd[u] r1[,r2],r3 */
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
v = oprrr(ctxt, int(p.As))
t = v & (1<<10 | 1) /* OE|Rc */
o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg))
o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, uint32(p.From.Reg))
o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r))
case 52: /* mtfsbNx cr(n) */
v = regoff(ctxt, &p.From) & 31
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(v), 0, 0)
case 53: /* mffsX ,fr1 */
o1 = AOP_RRR(OP_MFFS, uint32(p.To.Reg), 0, 0)
case 54: /* mov msr,r1; mov r1, msr*/
if oclass(&p.From) == C_REG {
if p.As == AMOVD {
o1 = AOP_RRR(OP_MTMSRD, uint32(p.From.Reg), 0, 0)
} else {
o1 = AOP_RRR(OP_MTMSR, uint32(p.From.Reg), 0, 0)
}
} else {
o1 = AOP_RRR(OP_MFMSR, uint32(p.To.Reg), 0, 0)
}
case 55: /* op Rb, Rd */
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.To.Reg), 0, uint32(p.From.Reg))
case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */
v = regoff(ctxt, &p.From)
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.To.Reg), uint32(v)&31)
if p.As == ASRAD && (v&0x20 != 0) {
o1 |= 1 << 1 /* mb[5] */
}
case 57: /* slw $sh,[s,]a -> rlwinm ... */
v = regoff(ctxt, &p.From)
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
/*
* Let user (gs) shoot himself in the foot.
* qc has already complained.
*
if(v < 0 || v > 31)
ctxt->diag("illegal shift %ld\n%P", v, p);
*/
if v < 0 {
v = 0
} else if v > 32 {
v = 32
}
if p.As == ASRW || p.As == ASRWCC { /* shift right */
mask[0] = uint8(v)
mask[1] = 31
v = 32 - v
} else {
mask[0] = 0
mask[1] = uint8(31 - v)
}
o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(r), uint32(v), uint32(mask[0]), uint32(mask[1]))
if p.As == ASLWCC || p.As == ASRWCC {
o1 |= 1 /* Rc */
}
case 58: /* logical $andcon,[s],a */
v = regoff(ctxt, &p.From)
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(p.To.Reg), uint32(r), uint32(v))
case 59: /* or/and $ucon,,r */
v = regoff(ctxt, &p.From)
r = int(p.Reg)
if r == 0 {
r = int(p.To.Reg)
}
o1 = LOP_IRR(uint32(opirr(ctxt, int(p.As)+ALAST)), uint32(p.To.Reg), uint32(r), uint32(v)>>16) /* oris, xoris, andis */
case 60: /* tw to,a,b */
r = int(regoff(ctxt, &p.From) & 31)
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
case 61: /* tw to,a,$simm */
r = int(regoff(ctxt, &p.From) & 31)
v = regoff(ctxt, &p.To)
o1 = AOP_IRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.Reg), uint32(v))
case 62: /* rlwmi $sh,s,$mask,a */
v = regoff(ctxt, &p.From)
maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, &p.From3)))
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(v))
o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
case 63: /* rlwmi b,s,$mask,a */
maskgen(ctxt, p, mask[:], uint32(regoff(ctxt, &p.From3)))
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg))
o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
case 64: /* mtfsf fr[, $m] {,fpcsr} */
if p.From3.Type != obj.TYPE_NONE {
v = regoff(ctxt, &p.From3) & 255
} else {
v = 255
}
o1 = OP_MTFSF | uint32(v)<<17 | uint32(p.From.Reg)<<11
case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
if p.To.Reg == 0 {
ctxt.Diag("must specify FPSCR(n)\n%v", p)
}
o1 = OP_MTFSFI | (uint32(p.To.Reg)&15)<<23 | (uint32(regoff(ctxt, &p.From))&31)<<12
case 66: /* mov spr,r1; mov r1,spr, also dcr */
if REG_R0 <= p.From.Reg && p.From.Reg <= REG_R31 {
r = int(p.From.Reg)
v = int32(p.To.Reg)
if REG_DCR0 <= v && v <= REG_DCR0+1023 {
o1 = OPVCC(31, 451, 0, 0) /* mtdcr */
} else {
o1 = OPVCC(31, 467, 0, 0) /* mtspr */
}
} else {
r = int(p.To.Reg)
v = int32(p.From.Reg)
if REG_DCR0 <= v && v <= REG_DCR0+1023 {
o1 = OPVCC(31, 323, 0, 0) /* mfdcr */
} else {
o1 = OPVCC(31, 339, 0, 0) /* mfspr */
}
}
o1 = AOP_RRR(o1, uint32(r), 0, 0) | (uint32(v)&0x1f)<<16 | ((uint32(v)>>5)&0x1f)<<11
case 67: /* mcrf crfD,crfS */
if p.From.Type != obj.TYPE_REG || p.From.Reg < REG_C0 || REG_C7 < p.From.Reg || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_C0 || REG_C7 < p.To.Reg {
ctxt.Diag("illegal CR field number\n%v", p)
}
o1 = AOP_RRR(OP_MCRF, ((uint32(p.To.Reg) & 7) << 2), ((uint32(p.From.Reg) & 7) << 2), 0)
case 68: /* mfcr rD; mfocrf CRM,rD */
if p.From.Type == obj.TYPE_REG && REG_C0 <= p.From.Reg && p.From.Reg <= REG_C7 {
v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */
o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) | 1<<20 | uint32(v)<<12 /* new form, mfocrf */
} else {
o1 = AOP_RRR(OP_MFCR, uint32(p.To.Reg), 0, 0) /* old form, whole register */
}
case 69: /* mtcrf CRM,rS */
if p.From3.Type != obj.TYPE_NONE {
if p.To.Reg != 0 {
ctxt.Diag("can't use both mask and CR(n)\n%v", p)
}
v = regoff(ctxt, &p.From3) & 0xff
} else {
if p.To.Reg == 0 {
v = 0xff /* CR */
} else {
v = 1 << uint(7-(p.To.Reg&7)) /* CR(n) */
}
}
o1 = AOP_RRR(OP_MTCRF, uint32(p.From.Reg), 0, 0) | uint32(v)<<12
case 70: /* [f]cmp r,r,cr*/
if p.Reg == 0 {
r = 0
} else {
r = (int(p.Reg) & 7) << 2
}
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
case 71: /* cmp[l] r,i,cr*/
if p.Reg == 0 {
r = 0
} else {
r = (int(p.Reg) & 7) << 2
}
o1 = AOP_RRR(uint32(opirr(ctxt, int(p.As))), uint32(r), uint32(p.From.Reg), 0) | uint32(regoff(ctxt, &p.To))&0xffff
case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
o1 = AOP_RRR(uint32(oprrr(ctxt, int(p.As))), uint32(p.From.Reg), 0, uint32(p.To.Reg))
case 73: /* mcrfs crfD,crfS */
if p.From.Type != obj.TYPE_REG || p.From.Reg != REG_FPSCR || p.To.Type != obj.TYPE_REG || p.To.Reg < REG_C0 || REG_C7 < p.To.Reg {
ctxt.Diag("illegal FPSCR/CR field number\n%v", p)
}
o1 = AOP_RRR(OP_MCRFS, ((uint32(p.To.Reg) & 7) << 2), ((0 & 7) << 2), 0)
case 77: /* syscall $scon, syscall Rx */
if p.From.Type == obj.TYPE_CONST {
if p.From.Offset > BIG || p.From.Offset < -BIG {
ctxt.Diag("illegal syscall, sysnum too large: %v", p)
}
o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, uint32(p.From.Offset))
} else if p.From.Type == obj.TYPE_REG {
o1 = LOP_RRR(OP_OR, REGZERO, uint32(p.From.Reg), uint32(p.From.Reg))
} else {
ctxt.Diag("illegal syscall: %v", p)
o1 = 0x7fe00008 // trap always
}
o2 = uint32(oprrr(ctxt, int(p.As)))
o3 = AOP_RRR(uint32(oprrr(ctxt, AXOR)), REGZERO, REGZERO, REGZERO) // XOR R0, R0
case 78: /* undef */
o1 = 0 /* "An instruction consisting entirely of binary 0s is guaranteed
always to be an illegal instruction." */
/* relocation operations */
case 74:
v = regoff(ctxt, &p.To)
o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
addaddrreloc(ctxt, p.To.Sym, &o1, &o2)
//if(dlm) reloc(&p->to, p->pc, 1);
case 75:
v = regoff(ctxt, &p.From)
o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
//if(dlm) reloc(&p->from, p->pc, 1);
case 76:
v = regoff(ctxt, &p.From)
o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
//if(dlm) reloc(&p->from, p->pc, 1);
}
out[0] = o1
out[1] = o2
out[2] = o3
out[3] = o4
out[4] = o5
return
}
func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
ctxt.Instoffset = 0
aclass(ctxt, a)
return ctxt.Instoffset
}
func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
return int32(vregoff(ctxt, a))
}
func oprrr(ctxt *obj.Link, a int) int32 {
switch a {
case AADD:
return int32(OPVCC(31, 266, 0, 0))
case AADDCC:
return int32(OPVCC(31, 266, 0, 1))
case AADDV:
return int32(OPVCC(31, 266, 1, 0))
case AADDVCC:
return int32(OPVCC(31, 266, 1, 1))
case AADDC:
return int32(OPVCC(31, 10, 0, 0))
case AADDCCC:
return int32(OPVCC(31, 10, 0, 1))
case AADDCV:
return int32(OPVCC(31, 10, 1, 0))
case AADDCVCC:
return int32(OPVCC(31, 10, 1, 1))
case AADDE:
return int32(OPVCC(31, 138, 0, 0))
case AADDECC:
return int32(OPVCC(31, 138, 0, 1))
case AADDEV:
return int32(OPVCC(31, 138, 1, 0))
case AADDEVCC:
return int32(OPVCC(31, 138, 1, 1))
case AADDME:
return int32(OPVCC(31, 234, 0, 0))
case AADDMECC:
return int32(OPVCC(31, 234, 0, 1))
case AADDMEV:
return int32(OPVCC(31, 234, 1, 0))
case AADDMEVCC:
return int32(OPVCC(31, 234, 1, 1))
case AADDZE:
return int32(OPVCC(31, 202, 0, 0))
case AADDZECC:
return int32(OPVCC(31, 202, 0, 1))
case AADDZEV:
return int32(OPVCC(31, 202, 1, 0))
case AADDZEVCC:
return int32(OPVCC(31, 202, 1, 1))
case AAND:
return int32(OPVCC(31, 28, 0, 0))
case AANDCC:
return int32(OPVCC(31, 28, 0, 1))
case AANDN:
return int32(OPVCC(31, 60, 0, 0))
case AANDNCC:
return int32(OPVCC(31, 60, 0, 1))
case ACMP:
return int32(OPVCC(31, 0, 0, 0) | 1<<21) /* L=1 */
case ACMPU:
return int32(OPVCC(31, 32, 0, 0) | 1<<21)
case ACMPW:
return int32(OPVCC(31, 0, 0, 0)) /* L=0 */
case ACMPWU:
return int32(OPVCC(31, 32, 0, 0))
case ACNTLZW:
return int32(OPVCC(31, 26, 0, 0))
case ACNTLZWCC:
return int32(OPVCC(31, 26, 0, 1))
case ACNTLZD:
return int32(OPVCC(31, 58, 0, 0))
case ACNTLZDCC:
return int32(OPVCC(31, 58, 0, 1))
case ACRAND:
return int32(OPVCC(19, 257, 0, 0))
case ACRANDN:
return int32(OPVCC(19, 129, 0, 0))
case ACREQV:
return int32(OPVCC(19, 289, 0, 0))
case ACRNAND:
return int32(OPVCC(19, 225, 0, 0))
case ACRNOR:
return int32(OPVCC(19, 33, 0, 0))
case ACROR:
return int32(OPVCC(19, 449, 0, 0))
case ACRORN:
return int32(OPVCC(19, 417, 0, 0))
case ACRXOR:
return int32(OPVCC(19, 193, 0, 0))
case ADCBF:
return int32(OPVCC(31, 86, 0, 0))
case ADCBI:
return int32(OPVCC(31, 470, 0, 0))
case ADCBST:
return int32(OPVCC(31, 54, 0, 0))
case ADCBT:
return int32(OPVCC(31, 278, 0, 0))
case ADCBTST:
return int32(OPVCC(31, 246, 0, 0))
case ADCBZ:
return int32(OPVCC(31, 1014, 0, 0))
case AREM,
ADIVW:
return int32(OPVCC(31, 491, 0, 0))
case AREMCC,
ADIVWCC:
return int32(OPVCC(31, 491, 0, 1))
case AREMV,
ADIVWV:
return int32(OPVCC(31, 491, 1, 0))
case AREMVCC,
ADIVWVCC:
return int32(OPVCC(31, 491, 1, 1))
case AREMU,
ADIVWU:
return int32(OPVCC(31, 459, 0, 0))
case AREMUCC,
ADIVWUCC:
return int32(OPVCC(31, 459, 0, 1))
case AREMUV,
ADIVWUV:
return int32(OPVCC(31, 459, 1, 0))
case AREMUVCC,
ADIVWUVCC:
return int32(OPVCC(31, 459, 1, 1))
case AREMD,
ADIVD:
return int32(OPVCC(31, 489, 0, 0))
case AREMDCC,
ADIVDCC:
return int32(OPVCC(31, 489, 0, 1))
case AREMDV,
ADIVDV:
return int32(OPVCC(31, 489, 1, 0))
case AREMDVCC,
ADIVDVCC:
return int32(OPVCC(31, 489, 1, 1))
case AREMDU,
ADIVDU:
return int32(OPVCC(31, 457, 0, 0))
case AREMDUCC,
ADIVDUCC:
return int32(OPVCC(31, 457, 0, 1))
case AREMDUV,
ADIVDUV:
return int32(OPVCC(31, 457, 1, 0))
case AREMDUVCC,
ADIVDUVCC:
return int32(OPVCC(31, 457, 1, 1))
case AEIEIO:
return int32(OPVCC(31, 854, 0, 0))
case AEQV:
return int32(OPVCC(31, 284, 0, 0))
case AEQVCC:
return int32(OPVCC(31, 284, 0, 1))
case AEXTSB:
return int32(OPVCC(31, 954, 0, 0))
case AEXTSBCC:
return int32(OPVCC(31, 954, 0, 1))
case AEXTSH:
return int32(OPVCC(31, 922, 0, 0))
case AEXTSHCC:
return int32(OPVCC(31, 922, 0, 1))
case AEXTSW:
return int32(OPVCC(31, 986, 0, 0))
case AEXTSWCC:
return int32(OPVCC(31, 986, 0, 1))
case AFABS:
return int32(OPVCC(63, 264, 0, 0))
case AFABSCC:
return int32(OPVCC(63, 264, 0, 1))
case AFADD:
return int32(OPVCC(63, 21, 0, 0))
case AFADDCC:
return int32(OPVCC(63, 21, 0, 1))
case AFADDS:
return int32(OPVCC(59, 21, 0, 0))
case AFADDSCC:
return int32(OPVCC(59, 21, 0, 1))
case AFCMPO:
return int32(OPVCC(63, 32, 0, 0))
case AFCMPU:
return int32(OPVCC(63, 0, 0, 0))
case AFCFID:
return int32(OPVCC(63, 846, 0, 0))
case AFCFIDCC:
return int32(OPVCC(63, 846, 0, 1))
case AFCTIW:
return int32(OPVCC(63, 14, 0, 0))
case AFCTIWCC:
return int32(OPVCC(63, 14, 0, 1))
case AFCTIWZ:
return int32(OPVCC(63, 15, 0, 0))
case AFCTIWZCC:
return int32(OPVCC(63, 15, 0, 1))
case AFCTID:
return int32(OPVCC(63, 814, 0, 0))
case AFCTIDCC:
return int32(OPVCC(63, 814, 0, 1))
case AFCTIDZ:
return int32(OPVCC(63, 815, 0, 0))
case AFCTIDZCC:
return int32(OPVCC(63, 815, 0, 1))
case AFDIV:
return int32(OPVCC(63, 18, 0, 0))
case AFDIVCC:
return int32(OPVCC(63, 18, 0, 1))
case AFDIVS:
return int32(OPVCC(59, 18, 0, 0))
case AFDIVSCC:
return int32(OPVCC(59, 18, 0, 1))
case AFMADD:
return int32(OPVCC(63, 29, 0, 0))
case AFMADDCC:
return int32(OPVCC(63, 29, 0, 1))
case AFMADDS:
return int32(OPVCC(59, 29, 0, 0))
case AFMADDSCC:
return int32(OPVCC(59, 29, 0, 1))
case AFMOVS,
AFMOVD:
return int32(OPVCC(63, 72, 0, 0)) /* load */
case AFMOVDCC:
return int32(OPVCC(63, 72, 0, 1))
case AFMSUB:
return int32(OPVCC(63, 28, 0, 0))
case AFMSUBCC:
return int32(OPVCC(63, 28, 0, 1))
case AFMSUBS:
return int32(OPVCC(59, 28, 0, 0))
case AFMSUBSCC:
return int32(OPVCC(59, 28, 0, 1))
case AFMUL:
return int32(OPVCC(63, 25, 0, 0))
case AFMULCC:
return int32(OPVCC(63, 25, 0, 1))
case AFMULS:
return int32(OPVCC(59, 25, 0, 0))
case AFMULSCC:
return int32(OPVCC(59, 25, 0, 1))
case AFNABS:
return int32(OPVCC(63, 136, 0, 0))
case AFNABSCC:
return int32(OPVCC(63, 136, 0, 1))
case AFNEG:
return int32(OPVCC(63, 40, 0, 0))
case AFNEGCC:
return int32(OPVCC(63, 40, 0, 1))
case AFNMADD:
return int32(OPVCC(63, 31, 0, 0))
case AFNMADDCC:
return int32(OPVCC(63, 31, 0, 1))
case AFNMADDS:
return int32(OPVCC(59, 31, 0, 0))
case AFNMADDSCC:
return int32(OPVCC(59, 31, 0, 1))
case AFNMSUB:
return int32(OPVCC(63, 30, 0, 0))
case AFNMSUBCC:
return int32(OPVCC(63, 30, 0, 1))
case AFNMSUBS:
return int32(OPVCC(59, 30, 0, 0))
case AFNMSUBSCC:
return int32(OPVCC(59, 30, 0, 1))
case AFRES:
return int32(OPVCC(59, 24, 0, 0))
case AFRESCC:
return int32(OPVCC(59, 24, 0, 1))
case AFRSP:
return int32(OPVCC(63, 12, 0, 0))
case AFRSPCC:
return int32(OPVCC(63, 12, 0, 1))
case AFRSQRTE:
return int32(OPVCC(63, 26, 0, 0))
case AFRSQRTECC:
return int32(OPVCC(63, 26, 0, 1))
case AFSEL:
return int32(OPVCC(63, 23, 0, 0))
case AFSELCC:
return int32(OPVCC(63, 23, 0, 1))
case AFSQRT:
return int32(OPVCC(63, 22, 0, 0))
case AFSQRTCC:
return int32(OPVCC(63, 22, 0, 1))
case AFSQRTS:
return int32(OPVCC(59, 22, 0, 0))
case AFSQRTSCC:
return int32(OPVCC(59, 22, 0, 1))
case AFSUB:
return int32(OPVCC(63, 20, 0, 0))
case AFSUBCC:
return int32(OPVCC(63, 20, 0, 1))
case AFSUBS:
return int32(OPVCC(59, 20, 0, 0))
case AFSUBSCC:
return int32(OPVCC(59, 20, 0, 1))
case AICBI:
return int32(OPVCC(31, 982, 0, 0))
case AISYNC:
return int32(OPVCC(19, 150, 0, 0))
case AMTFSB0:
return int32(OPVCC(63, 70, 0, 0))
case AMTFSB0CC:
return int32(OPVCC(63, 70, 0, 1))
case AMTFSB1:
return int32(OPVCC(63, 38, 0, 0))
case AMTFSB1CC:
return int32(OPVCC(63, 38, 0, 1))
case AMULHW:
return int32(OPVCC(31, 75, 0, 0))
case AMULHWCC:
return int32(OPVCC(31, 75, 0, 1))
case AMULHWU:
return int32(OPVCC(31, 11, 0, 0))
case AMULHWUCC:
return int32(OPVCC(31, 11, 0, 1))
case AMULLW:
return int32(OPVCC(31, 235, 0, 0))
case AMULLWCC:
return int32(OPVCC(31, 235, 0, 1))
case AMULLWV:
return int32(OPVCC(31, 235, 1, 0))
case AMULLWVCC:
return int32(OPVCC(31, 235, 1, 1))
case AMULHD:
return int32(OPVCC(31, 73, 0, 0))
case AMULHDCC:
return int32(OPVCC(31, 73, 0, 1))
case AMULHDU:
return int32(OPVCC(31, 9, 0, 0))
case AMULHDUCC:
return int32(OPVCC(31, 9, 0, 1))
case AMULLD:
return int32(OPVCC(31, 233, 0, 0))
case AMULLDCC:
return int32(OPVCC(31, 233, 0, 1))
case AMULLDV:
return int32(OPVCC(31, 233, 1, 0))
case AMULLDVCC:
return int32(OPVCC(31, 233, 1, 1))
case ANAND:
return int32(OPVCC(31, 476, 0, 0))
case ANANDCC:
return int32(OPVCC(31, 476, 0, 1))
case ANEG:
return int32(OPVCC(31, 104, 0, 0))
case ANEGCC:
return int32(OPVCC(31, 104, 0, 1))
case ANEGV:
return int32(OPVCC(31, 104, 1, 0))
case ANEGVCC:
return int32(OPVCC(31, 104, 1, 1))
case ANOR:
return int32(OPVCC(31, 124, 0, 0))
case ANORCC:
return int32(OPVCC(31, 124, 0, 1))
case AOR:
return int32(OPVCC(31, 444, 0, 0))
case AORCC:
return int32(OPVCC(31, 444, 0, 1))
case AORN:
return int32(OPVCC(31, 412, 0, 0))
case AORNCC:
return int32(OPVCC(31, 412, 0, 1))
case ARFI:
return int32(OPVCC(19, 50, 0, 0))
case ARFCI:
return int32(OPVCC(19, 51, 0, 0))
case ARFID:
return int32(OPVCC(19, 18, 0, 0))
case AHRFID:
return int32(OPVCC(19, 274, 0, 0))
case ARLWMI:
return int32(OPVCC(20, 0, 0, 0))
case ARLWMICC:
return int32(OPVCC(20, 0, 0, 1))
case ARLWNM:
return int32(OPVCC(23, 0, 0, 0))
case ARLWNMCC:
return int32(OPVCC(23, 0, 0, 1))
case ARLDCL:
return int32(OPVCC(30, 8, 0, 0))
case ARLDCR:
return int32(OPVCC(30, 9, 0, 0))
case ASYSCALL:
return int32(OPVCC(17, 1, 0, 0))
case ASLW:
return int32(OPVCC(31, 24, 0, 0))
case ASLWCC:
return int32(OPVCC(31, 24, 0, 1))
case ASLD:
return int32(OPVCC(31, 27, 0, 0))
case ASLDCC:
return int32(OPVCC(31, 27, 0, 1))
case ASRAW:
return int32(OPVCC(31, 792, 0, 0))
case ASRAWCC:
return int32(OPVCC(31, 792, 0, 1))
case ASRAD:
return int32(OPVCC(31, 794, 0, 0))
case ASRADCC:
return int32(OPVCC(31, 794, 0, 1))
case ASRW:
return int32(OPVCC(31, 536, 0, 0))
case ASRWCC:
return int32(OPVCC(31, 536, 0, 1))
case ASRD:
return int32(OPVCC(31, 539, 0, 0))
case ASRDCC:
return int32(OPVCC(31, 539, 0, 1))
case ASUB:
return int32(OPVCC(31, 40, 0, 0))
case ASUBCC:
return int32(OPVCC(31, 40, 0, 1))
case ASUBV:
return int32(OPVCC(31, 40, 1, 0))
case ASUBVCC:
return int32(OPVCC(31, 40, 1, 1))
case ASUBC:
return int32(OPVCC(31, 8, 0, 0))
case ASUBCCC:
return int32(OPVCC(31, 8, 0, 1))
case ASUBCV:
return int32(OPVCC(31, 8, 1, 0))
case ASUBCVCC:
return int32(OPVCC(31, 8, 1, 1))
case ASUBE:
return int32(OPVCC(31, 136, 0, 0))
case ASUBECC:
return int32(OPVCC(31, 136, 0, 1))
case ASUBEV:
return int32(OPVCC(31, 136, 1, 0))
case ASUBEVCC:
return int32(OPVCC(31, 136, 1, 1))
case ASUBME:
return int32(OPVCC(31, 232, 0, 0))
case ASUBMECC:
return int32(OPVCC(31, 232, 0, 1))
case ASUBMEV:
return int32(OPVCC(31, 232, 1, 0))
case ASUBMEVCC:
return int32(OPVCC(31, 232, 1, 1))
case ASUBZE:
return int32(OPVCC(31, 200, 0, 0))
case ASUBZECC:
return int32(OPVCC(31, 200, 0, 1))
case ASUBZEV:
return int32(OPVCC(31, 200, 1, 0))
case ASUBZEVCC:
return int32(OPVCC(31, 200, 1, 1))
case ASYNC:
return int32(OPVCC(31, 598, 0, 0))
case APTESYNC:
return int32(OPVCC(31, 598, 0, 0) | 2<<21)
case ATLBIE:
return int32(OPVCC(31, 306, 0, 0))
case ATLBIEL:
return int32(OPVCC(31, 274, 0, 0))
case ATLBSYNC:
return int32(OPVCC(31, 566, 0, 0))
case ASLBIA:
return int32(OPVCC(31, 498, 0, 0))
case ASLBIE:
return int32(OPVCC(31, 434, 0, 0))
case ASLBMFEE:
return int32(OPVCC(31, 915, 0, 0))
case ASLBMFEV:
return int32(OPVCC(31, 851, 0, 0))
case ASLBMTE:
return int32(OPVCC(31, 402, 0, 0))
case ATW:
return int32(OPVCC(31, 4, 0, 0))
case ATD:
return int32(OPVCC(31, 68, 0, 0))
case AXOR:
return int32(OPVCC(31, 316, 0, 0))
case AXORCC:
return int32(OPVCC(31, 316, 0, 1))
}
ctxt.Diag("bad r/r opcode %v", Aconv(a))
return 0
}
func opirr(ctxt *obj.Link, a int) int32 {
switch a {
case AADD:
return int32(OPVCC(14, 0, 0, 0))
case AADDC:
return int32(OPVCC(12, 0, 0, 0))
case AADDCCC:
return int32(OPVCC(13, 0, 0, 0))
case AADD + ALAST:
return int32(OPVCC(15, 0, 0, 0)) /* ADDIS/CAU */
case AANDCC:
return int32(OPVCC(28, 0, 0, 0))
case AANDCC + ALAST:
return int32(OPVCC(29, 0, 0, 0)) /* ANDIS./ANDIU. */
case ABR:
return int32(OPVCC(18, 0, 0, 0))
case ABL:
return int32(OPVCC(18, 0, 0, 0) | 1)
case obj.ADUFFZERO:
return int32(OPVCC(18, 0, 0, 0) | 1)
case obj.ADUFFCOPY:
return int32(OPVCC(18, 0, 0, 0) | 1)
case ABC:
return int32(OPVCC(16, 0, 0, 0))
case ABCL:
return int32(OPVCC(16, 0, 0, 0) | 1)
case ABEQ:
return int32(AOP_RRR(16<<26, 12, 2, 0))
case ABGE:
return int32(AOP_RRR(16<<26, 4, 0, 0))
case ABGT:
return int32(AOP_RRR(16<<26, 12, 1, 0))
case ABLE:
return int32(AOP_RRR(16<<26, 4, 1, 0))
case ABLT:
return int32(AOP_RRR(16<<26, 12, 0, 0))
case ABNE:
return int32(AOP_RRR(16<<26, 4, 2, 0))
case ABVC:
return int32(AOP_RRR(16<<26, 4, 3, 0))
case ABVS:
return int32(AOP_RRR(16<<26, 12, 3, 0))
case ACMP:
return int32(OPVCC(11, 0, 0, 0) | 1<<21) /* L=1 */
case ACMPU:
return int32(OPVCC(10, 0, 0, 0) | 1<<21)
case ACMPW:
return int32(OPVCC(11, 0, 0, 0)) /* L=0 */
case ACMPWU:
return int32(OPVCC(10, 0, 0, 0))
case ALSW:
return int32(OPVCC(31, 597, 0, 0))
case AMULLW:
return int32(OPVCC(7, 0, 0, 0))
case AOR:
return int32(OPVCC(24, 0, 0, 0))
case AOR + ALAST:
return int32(OPVCC(25, 0, 0, 0)) /* ORIS/ORIU */
case ARLWMI:
return int32(OPVCC(20, 0, 0, 0)) /* rlwimi */
case ARLWMICC:
return int32(OPVCC(20, 0, 0, 1))
case ARLDMI:
return int32(OPVCC(30, 0, 0, 0) | 3<<2) /* rldimi */
case ARLDMICC:
return int32(OPVCC(30, 0, 0, 1) | 3<<2)
case ARLWNM:
return int32(OPVCC(21, 0, 0, 0)) /* rlwinm */
case ARLWNMCC:
return int32(OPVCC(21, 0, 0, 1))
case ARLDCL:
return int32(OPVCC(30, 0, 0, 0)) /* rldicl */
case ARLDCLCC:
return int32(OPVCC(30, 0, 0, 1))
case ARLDCR:
return int32(OPVCC(30, 1, 0, 0)) /* rldicr */
case ARLDCRCC:
return int32(OPVCC(30, 1, 0, 1))
case ARLDC:
return int32(OPVCC(30, 0, 0, 0) | 2<<2)
case ARLDCCC:
return int32(OPVCC(30, 0, 0, 1) | 2<<2)
case ASRAW:
return int32(OPVCC(31, 824, 0, 0))
case ASRAWCC:
return int32(OPVCC(31, 824, 0, 1))
case ASRAD:
return int32(OPVCC(31, (413 << 1), 0, 0))
case ASRADCC:
return int32(OPVCC(31, (413 << 1), 0, 1))
case ASTSW:
return int32(OPVCC(31, 725, 0, 0))
case ASUBC:
return int32(OPVCC(8, 0, 0, 0))
case ATW:
return int32(OPVCC(3, 0, 0, 0))
case ATD:
return int32(OPVCC(2, 0, 0, 0))
case AXOR:
return int32(OPVCC(26, 0, 0, 0)) /* XORIL */
case AXOR + ALAST:
return int32(OPVCC(27, 0, 0, 0)) /* XORIU */
}
ctxt.Diag("bad opcode i/r %v", Aconv(a))
return 0
}
/*
* load o(a),d
*/
func opload(ctxt *obj.Link, a int) int32 {
switch a {
case AMOVD:
return int32(OPVCC(58, 0, 0, 0)) /* ld */
case AMOVDU:
return int32(OPVCC(58, 0, 0, 1)) /* ldu */
case AMOVWZ:
return int32(OPVCC(32, 0, 0, 0)) /* lwz */
case AMOVWZU:
return int32(OPVCC(33, 0, 0, 0)) /* lwzu */
case AMOVW:
return int32(OPVCC(58, 0, 0, 0) | 1<<1) /* lwa */
/* no AMOVWU */
case AMOVB,
AMOVBZ:
return int32(OPVCC(34, 0, 0, 0))
/* load */
case AMOVBU,
AMOVBZU:
return int32(OPVCC(35, 0, 0, 0))
case AFMOVD:
return int32(OPVCC(50, 0, 0, 0))
case AFMOVDU:
return int32(OPVCC(51, 0, 0, 0))
case AFMOVS:
return int32(OPVCC(48, 0, 0, 0))
case AFMOVSU:
return int32(OPVCC(49, 0, 0, 0))
case AMOVH:
return int32(OPVCC(42, 0, 0, 0))
case AMOVHU:
return int32(OPVCC(43, 0, 0, 0))
case AMOVHZ:
return int32(OPVCC(40, 0, 0, 0))
case AMOVHZU:
return int32(OPVCC(41, 0, 0, 0))
case AMOVMW:
return int32(OPVCC(46, 0, 0, 0)) /* lmw */
}
ctxt.Diag("bad load opcode %v", Aconv(a))
return 0
}
/*
* indexed load a(b),d
*/
func oploadx(ctxt *obj.Link, a int) int32 {
switch a {
case AMOVWZ:
return int32(OPVCC(31, 23, 0, 0)) /* lwzx */
case AMOVWZU:
return int32(OPVCC(31, 55, 0, 0)) /* lwzux */
case AMOVW:
return int32(OPVCC(31, 341, 0, 0)) /* lwax */
case AMOVWU:
return int32(OPVCC(31, 373, 0, 0)) /* lwaux */
case AMOVB,
AMOVBZ:
return int32(OPVCC(31, 87, 0, 0)) /* lbzx */
case AMOVBU,
AMOVBZU:
return int32(OPVCC(31, 119, 0, 0)) /* lbzux */
case AFMOVD:
return int32(OPVCC(31, 599, 0, 0)) /* lfdx */
case AFMOVDU:
return int32(OPVCC(31, 631, 0, 0)) /* lfdux */
case AFMOVS:
return int32(OPVCC(31, 535, 0, 0)) /* lfsx */
case AFMOVSU:
return int32(OPVCC(31, 567, 0, 0)) /* lfsux */
case AMOVH:
return int32(OPVCC(31, 343, 0, 0)) /* lhax */
case AMOVHU:
return int32(OPVCC(31, 375, 0, 0)) /* lhaux */
case AMOVHBR:
return int32(OPVCC(31, 790, 0, 0)) /* lhbrx */
case AMOVWBR:
return int32(OPVCC(31, 534, 0, 0)) /* lwbrx */
case AMOVHZ:
return int32(OPVCC(31, 279, 0, 0)) /* lhzx */
case AMOVHZU:
return int32(OPVCC(31, 311, 0, 0)) /* lhzux */
case AECIWX:
return int32(OPVCC(31, 310, 0, 0)) /* eciwx */
case ALWAR:
return int32(OPVCC(31, 20, 0, 0)) /* lwarx */
case ALDAR:
return int32(OPVCC(31, 84, 0, 0))
case ALSW:
return int32(OPVCC(31, 533, 0, 0)) /* lswx */
case AMOVD:
return int32(OPVCC(31, 21, 0, 0)) /* ldx */
case AMOVDU:
return int32(OPVCC(31, 53, 0, 0)) /* ldux */
}
ctxt.Diag("bad loadx opcode %v", Aconv(a))
return 0
}
/*
* store s,o(d)
*/
func opstore(ctxt *obj.Link, a int) int32 {
switch a {
case AMOVB,
AMOVBZ:
return int32(OPVCC(38, 0, 0, 0)) /* stb */
case AMOVBU,
AMOVBZU:
return int32(OPVCC(39, 0, 0, 0)) /* stbu */
case AFMOVD:
return int32(OPVCC(54, 0, 0, 0)) /* stfd */
case AFMOVDU:
return int32(OPVCC(55, 0, 0, 0)) /* stfdu */
case AFMOVS:
return int32(OPVCC(52, 0, 0, 0)) /* stfs */
case AFMOVSU:
return int32(OPVCC(53, 0, 0, 0)) /* stfsu */
case AMOVHZ,
AMOVH:
return int32(OPVCC(44, 0, 0, 0)) /* sth */
case AMOVHZU,
AMOVHU:
return int32(OPVCC(45, 0, 0, 0)) /* sthu */
case AMOVMW:
return int32(OPVCC(47, 0, 0, 0)) /* stmw */
case ASTSW:
return int32(OPVCC(31, 725, 0, 0)) /* stswi */
case AMOVWZ,
AMOVW:
return int32(OPVCC(36, 0, 0, 0)) /* stw */
case AMOVWZU,
AMOVWU:
return int32(OPVCC(37, 0, 0, 0)) /* stwu */
case AMOVD:
return int32(OPVCC(62, 0, 0, 0)) /* std */
case AMOVDU:
return int32(OPVCC(62, 0, 0, 1)) /* stdu */
}
ctxt.Diag("unknown store opcode %v", Aconv(a))
return 0
}
/*
* indexed store s,a(b)
*/
func opstorex(ctxt *obj.Link, a int) int32 {
switch a {
case AMOVB,
AMOVBZ:
return int32(OPVCC(31, 215, 0, 0)) /* stbx */
case AMOVBU,
AMOVBZU:
return int32(OPVCC(31, 247, 0, 0)) /* stbux */
case AFMOVD:
return int32(OPVCC(31, 727, 0, 0)) /* stfdx */
case AFMOVDU:
return int32(OPVCC(31, 759, 0, 0)) /* stfdux */
case AFMOVS:
return int32(OPVCC(31, 663, 0, 0)) /* stfsx */
case AFMOVSU:
return int32(OPVCC(31, 695, 0, 0)) /* stfsux */
case AMOVHZ,
AMOVH:
return int32(OPVCC(31, 407, 0, 0)) /* sthx */
case AMOVHBR:
return int32(OPVCC(31, 918, 0, 0)) /* sthbrx */
case AMOVHZU,
AMOVHU:
return int32(OPVCC(31, 439, 0, 0)) /* sthux */
case AMOVWZ,
AMOVW:
return int32(OPVCC(31, 151, 0, 0)) /* stwx */
case AMOVWZU,
AMOVWU:
return int32(OPVCC(31, 183, 0, 0)) /* stwux */
case ASTSW:
return int32(OPVCC(31, 661, 0, 0)) /* stswx */
case AMOVWBR:
return int32(OPVCC(31, 662, 0, 0)) /* stwbrx */
case ASTWCCC:
return int32(OPVCC(31, 150, 0, 1)) /* stwcx. */
case ASTDCCC:
return int32(OPVCC(31, 214, 0, 1)) /* stwdx. */
case AECOWX:
return int32(OPVCC(31, 438, 0, 0)) /* ecowx */
case AMOVD:
return int32(OPVCC(31, 149, 0, 0)) /* stdx */
case AMOVDU:
return int32(OPVCC(31, 181, 0, 0)) /* stdux */
}
ctxt.Diag("unknown storex opcode %v", Aconv(a))
return 0
}