...

Source file src/pkg/cmd/vendor/golang.org/x/arch/ppc64/ppc64asm/gnu.go

     1	// Copyright 2014 The Go Authors.  All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package ppc64asm
     6	
     7	import (
     8		"bytes"
     9		"fmt"
    10		"strings"
    11	)
    12	
    13	// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
    14	// This form typically matches the syntax defined in the Power ISA Reference Manual.
    15	func GNUSyntax(inst Inst) string {
    16		var buf bytes.Buffer
    17		// When there are all 0s, identify them as the disassembler
    18		// in binutils would.
    19		if inst.Enc == 0 {
    20			return ".long 0x0"
    21		} else if inst.Op == 0 {
    22			return "error: unknown instruction"
    23		}
    24		buf.WriteString(inst.Op.String())
    25		sep := " "
    26		for i, arg := range inst.Args[:] {
    27			if arg == nil {
    28				break
    29			}
    30			text := gnuArg(&inst, i, arg)
    31			if text == "" {
    32				continue
    33			}
    34			buf.WriteString(sep)
    35			sep = ","
    36			buf.WriteString(text)
    37		}
    38		return buf.String()
    39	}
    40	
    41	// gnuArg formats arg (which is the argIndex's arg in inst) according to GNU rules.
    42	// NOTE: because GNUSyntax is the only caller of this func, and it receives a copy
    43	//       of inst, it's ok to modify inst.Args here.
    44	func gnuArg(inst *Inst, argIndex int, arg Arg) string {
    45		// special cases for load/store instructions
    46		if _, ok := arg.(Offset); ok {
    47			if argIndex+1 == len(inst.Args) || inst.Args[argIndex+1] == nil {
    48				panic(fmt.Errorf("wrong table: offset not followed by register"))
    49			}
    50		}
    51		switch arg := arg.(type) {
    52		case Reg:
    53			if isLoadStoreOp(inst.Op) && argIndex == 1 && arg == R0 {
    54				return "0"
    55			}
    56			return arg.String()
    57		case CondReg:
    58			if arg == CR0 && strings.HasPrefix(inst.Op.String(), "cmp") {
    59				return "" // don't show cr0 for cmp instructions
    60			} else if arg >= CR0 {
    61				return fmt.Sprintf("cr%d", int(arg-CR0))
    62			}
    63			bit := [4]string{"lt", "gt", "eq", "so"}[(arg-Cond0LT)%4]
    64			if arg <= Cond0SO {
    65				return bit
    66			}
    67			return fmt.Sprintf("4*cr%d+%s", int(arg-Cond0LT)/4, bit)
    68		case Imm:
    69			return fmt.Sprintf("%d", arg)
    70		case SpReg:
    71			return fmt.Sprintf("%d", int(arg))
    72		case PCRel:
    73			return fmt.Sprintf(".%+#x", int(arg))
    74		case Label:
    75			return fmt.Sprintf("%#x", uint32(arg))
    76		case Offset:
    77			reg := inst.Args[argIndex+1].(Reg)
    78			removeArg(inst, argIndex+1)
    79			if reg == R0 {
    80				return fmt.Sprintf("%d(0)", int(arg))
    81			}
    82			return fmt.Sprintf("%d(r%d)", int(arg), reg-R0)
    83		}
    84		return fmt.Sprintf("???(%v)", arg)
    85	}
    86	
    87	// removeArg removes the arg in inst.Args[index].
    88	func removeArg(inst *Inst, index int) {
    89		for i := index; i < len(inst.Args); i++ {
    90			if i+1 < len(inst.Args) {
    91				inst.Args[i] = inst.Args[i+1]
    92			} else {
    93				inst.Args[i] = nil
    94			}
    95		}
    96	}
    97	
    98	// isLoadStoreOp returns true if op is a load or store instruction
    99	func isLoadStoreOp(op Op) bool {
   100		switch op {
   101		case LBZ, LBZU, LBZX, LBZUX:
   102			return true
   103		case LHZ, LHZU, LHZX, LHZUX:
   104			return true
   105		case LHA, LHAU, LHAX, LHAUX:
   106			return true
   107		case LWZ, LWZU, LWZX, LWZUX:
   108			return true
   109		case LWA, LWAX, LWAUX:
   110			return true
   111		case LD, LDU, LDX, LDUX:
   112			return true
   113		case LQ:
   114			return true
   115		case STB, STBU, STBX, STBUX:
   116			return true
   117		case STH, STHU, STHX, STHUX:
   118			return true
   119		case STW, STWU, STWX, STWUX:
   120			return true
   121		case STD, STDU, STDX, STDUX:
   122			return true
   123		case STQ:
   124			return true
   125		case LHBRX, LWBRX, STHBRX, STWBRX:
   126			return true
   127		}
   128		return false
   129	}
   130	

View as plain text