// Copyright 2017 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 x86csv provides means to work with "x86.csv".
// Only latest version of "x86.csv" format is supported.
//
// Terminology:
//   given "OPCODE [ARGS...]" line;
// Opcode - instruction name/mnemonic/class.
// Args   - instruction operands.
// Syntax - Opcode with Args.
package x86csv

import (
	"strings"
)

// An Inst describes single x86 instruction encoding form.
type Inst struct {
	// Intel syntax (example: "SHR r/m32, imm8").
	Intel string

	// Go assembler syntax (example: "SHRL imm8, r/m32").
	Go string

	// GNU binutils syntax (example: "shrl imm8, r/m32").
	GNU string

	// Binary encoding (example: "C1 /4 ib").
	Encoding string

	// Validity in 32bit mode ("V", "I" or "N.E.").
	Mode32 string

	// Validity in 64bit mode ("V", "I", "N.E.", "N.P.", "N.I." or "N.S.").
	Mode64 string

	// CPUID feature flags required (comma-separated).
	CPUID string

	// Hints about instruction (comma-separated).
	// See "x86spec" package to see detailed overview of possible
	// tags and their meaning.
	Tags string

	// Read/write action of the instruction on its arguments, in Intel order.
	// For example, "rw,r" denotes that "SHR r/m32, imm8" reads and writes
	// its first argument but only reads its second argument.
	Action string

	// Whether Intel syntax has encoding forms distinguished only by
	// operand size, like most arithmetic instructions ("" or "Y").
	Multisize string

	// DataSize is the size of the data operation in bits ("8" for MOVB, "16" for MOVW, and so on).
	DataSize string
}

// IntelOpcode returns the opcode in the Intel syntax.
func (inst *Inst) IntelOpcode() string { return instOpcode(inst.Intel) }

// GoOpcode returns the opcode in Go (Plan9) syntax.
func (inst *Inst) GoOpcode() string { return instOpcode(inst.Go) }

// GNUOpcode returns the opcode in GNU binutils (mostly AT&T) syntax.
func (inst *Inst) GNUOpcode() string { return instOpcode(inst.GNU) }

// IntelArgs returns the arguments in the Intel syntax.
func (inst *Inst) IntelArgs() []string { return instArgs(inst.Intel) }

// GoArgs returns the arguments in Go (Plan9) syntax.
func (inst *Inst) GoArgs() []string { return instArgs(inst.Go) }

// GNUArgs returns the arguments in GNU binutils (mostly AT&T) syntax.
func (inst *Inst) GNUArgs() []string { return instArgs(inst.GNU) }

// HasTag reports whether inst tag list contains the specified tag.
func (inst *Inst) HasTag(tag string) bool {
	i := strings.Index(inst.Tags, tag)
	if i == -1 {
		return false
	}
	leftOK := i == 0 ||
		(inst.Tags[i-1] == ',')
	rigthOK := i+len(tag) == len(inst.Tags) ||
		(inst.Tags[i+len(tag)] == ',')
	return leftOK && rigthOK
}

// instOpcode returns the opcode from an instruction syntax.
func instOpcode(syntax string) string {
	i := strings.Index(syntax, " ")
	if i == -1 {
		return syntax
	}
	return syntax[:i]
}

// instArgs returns the arguments from an instruction syntax.
func instArgs(syntax string) []string {
	i := strings.Index(syntax, " ")
	if i < 0 {
		return nil
	}
	args := strings.Split(syntax[i+1:], ",")
	for i := range args {
		args[i] = strings.TrimSpace(args[i])
	}
	return args
}
