// Copyright 2014 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ppc64asm

import (
	"bytes"
	"fmt"
	"strings"
)

// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
// This form typically matches the syntax defined in the Power ISA Reference Manual.
func GNUSyntax(inst Inst) string {
	var buf bytes.Buffer
	// When there are all 0s, identify them as the disassembler
	// in binutils would.
	if inst.Enc == 0 {
		return ".long 0x0"
	} else if inst.Op == 0 {
		return "error: unknown instruction"
	}
	buf.WriteString(inst.Op.String())
	sep := " "
	for i, arg := range inst.Args[:] {
		if arg == nil {
			break
		}
		text := gnuArg(&inst, i, arg)
		if text == "" {
			continue
		}
		buf.WriteString(sep)
		sep = ","
		buf.WriteString(text)
	}
	return buf.String()
}

// gnuArg formats arg (which is the argIndex's arg in inst) according to GNU rules.
// NOTE: because GNUSyntax is the only caller of this func, and it receives a copy
//       of inst, it's ok to modify inst.Args here.
func gnuArg(inst *Inst, argIndex int, arg Arg) string {
	// special cases for load/store instructions
	if _, ok := arg.(Offset); ok {
		if argIndex+1 == len(inst.Args) || inst.Args[argIndex+1] == nil {
			panic(fmt.Errorf("wrong table: offset not followed by register"))
		}
	}
	switch arg := arg.(type) {
	case Reg:
		if isLoadStoreOp(inst.Op) && argIndex == 1 && arg == R0 {
			return "0"
		}
		return arg.String()
	case CondReg:
		if arg == CR0 && strings.HasPrefix(inst.Op.String(), "cmp") {
			return "" // don't show cr0 for cmp instructions
		} else if arg >= CR0 {
			return fmt.Sprintf("cr%d", int(arg-CR0))
		}
		bit := [4]string{"lt", "gt", "eq", "so"}[(arg-Cond0LT)%4]
		if arg <= Cond0SO {
			return bit
		}
		return fmt.Sprintf("4*cr%d+%s", int(arg-Cond0LT)/4, bit)
	case Imm:
		return fmt.Sprintf("%d", arg)
	case SpReg:
		return fmt.Sprintf("%d", int(arg))
	case PCRel:
		return fmt.Sprintf(".%+#x", int(arg))
	case Label:
		return fmt.Sprintf("%#x", uint32(arg))
	case Offset:
		reg := inst.Args[argIndex+1].(Reg)
		removeArg(inst, argIndex+1)
		if reg == R0 {
			return fmt.Sprintf("%d(0)", int(arg))
		}
		return fmt.Sprintf("%d(r%d)", int(arg), reg-R0)
	}
	return fmt.Sprintf("???(%v)", arg)
}

// removeArg removes the arg in inst.Args[index].
func removeArg(inst *Inst, index int) {
	for i := index; i < len(inst.Args); i++ {
		if i+1 < len(inst.Args) {
			inst.Args[i] = inst.Args[i+1]
		} else {
			inst.Args[i] = nil
		}
	}
}

// isLoadStoreOp returns true if op is a load or store instruction
func isLoadStoreOp(op Op) bool {
	switch op {
	case LBZ, LBZU, LBZX, LBZUX:
		return true
	case LHZ, LHZU, LHZX, LHZUX:
		return true
	case LHA, LHAU, LHAX, LHAUX:
		return true
	case LWZ, LWZU, LWZX, LWZUX:
		return true
	case LWA, LWAX, LWAUX:
		return true
	case LD, LDU, LDX, LDUX:
		return true
	case LQ:
		return true
	case STB, STBU, STBX, STBUX:
		return true
	case STH, STHU, STHX, STHUX:
		return true
	case STW, STWU, STWX, STWUX:
		return true
	case STD, STDU, STDX, STDUX:
		return true
	case STQ:
		return true
	case LHBRX, LWBRX, STHBRX, STWBRX:
		return true
	}
	return false
}
