// 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 (
	"encoding/binary"
	"strings"
	"testing"
)

func TestObjdumpPowerTestdata(t *testing.T) { testObjdump(t, testdataCases(t)) }
func TestObjdumpPowerManual(t *testing.T)   { testObjdump(t, hexCases(t, objdumpManualTests)) }

// Disable this for now since generating all possible bit combinations within a word
// generates lots of ppc64x instructions not possible with golang so not worth supporting..
//func TestObjdumpPowerRandom(t *testing.T)   { testObjdump(t, randomCases(t)) }

// objdumpManualTests holds test cases that will be run by TestObjdumpARMManual.
// If you are debugging a few cases that turned up in a longer run, it can be useful
// to list them here and then use -run=Manual, particularly with tracing enabled.
// Note that these are byte sequences, so they must be reversed from the usual
// word presentation.
var objdumpManualTests = `
6d746162
4c040000
88000017
`

// allowedMismatchObjdump reports whether the mismatch between text and dec
// should be allowed by the test.
func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
	if hasPrefix(dec.text, deleted...) {
		return true
	}

	// we support more instructions than binutils
	if strings.Contains(dec.text, ".long") {
		return true
	}

	if hasPrefix(text, "error:") {
		if hasPrefix(dec.text, unsupported...) {
			return true
		}
	}

	switch inst.Op {
	case BC, BCA, BL, BLA, BCL, BCLA, TDI, TWI, TW, TD:
		return true // TODO(minux): we lack the support for extended opcodes here
	case RLWNM, RLWNM_, RLDICL, RLDICL_, RLWINM, RLWINM_, RLDCL, RLDCL_:
		return true // TODO(minux): we lack the support for extended opcodes here
	case DCBTST, DCBT:
		return true // objdump uses the embedded argument order, we use the server argument order
	case MTFSF, MTFSF_: // objdump doesn't show the last two arguments
		return true
	case VSPLTB, VSPLTH, VSPLTW: // objdump generates unreasonable result "vspltw v6,v19,4" for 10c49a8c, the last 4 should be 0.
		return true
	}
	if hasPrefix(text, "evm", "evl", "efs") { // objdump will disassemble them wrong (e.g. evmhoumia as vsldoi)
		return true
	}

	if len(dec.enc) >= 4 {
		_ = binary.BigEndian.Uint32(dec.enc[:4])
	}

	return false
}

// Instructions known to libopcodes (or xed) but not to us.
// TODO(minux): those single precision instructions are missing from ppc64.csv
// those data cache instructions are deprecated, but must be treated as no-ops, see 4.3.2.1 pg. 774.
var unsupported = strings.Fields(`
fmsubs
fmsubs.
fnmadds
fnmadds.
fnmsubs
fnmsubs.
fmuls
fmuls.
fdivs
fdivs.
fadds
fadds.
fsubs
fsubs.
dst
dstst
dssall
`)

// Instructions explicitly dropped in Power ISA that were in POWER architecture.
// See A.30 Deleted Instructions and A.31 Discontiued Opcodes
var deleted = strings.Fields(`
abs
clcs
clf
cli
dclst
div
divs
doz
dozi
lscbx
maskg
maskir
mfsri
mul
nabs
rac
rfi
rfsvc
rlmi
rrib
sle
sleq
sliq
slliq
sllq
slq
sraiq
sraq
sre
srea
sreq
sriq
srliq
srlq
srq
maskg`)
