// Copyright 2009 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 gc

import "cmd/internal/obj"

func CASE(a int, b int) int {
	return a<<16 | b
}

func overlap_cplx(f *Node, t *Node) bool {
	// check whether f and t could be overlapping stack references.
	// not exact, because it's hard to check for the stack register
	// in portable code.  close enough: worst case we will allocate
	// an extra temporary and the registerizer will clean it up.
	return f.Op == OINDREG && t.Op == OINDREG && f.Xoffset+f.Type.Width >= t.Xoffset && t.Xoffset+t.Type.Width >= f.Xoffset
}

func Complexbool(op int, nl *Node, nr *Node, true_ bool, likely int, to *obj.Prog) {
	var tnl Node

	// make both sides addable in ullman order
	if nr != nil {
		if nl.Ullman > nr.Ullman && nl.Addable == 0 {
			Tempname(&tnl, nl.Type)
			Cgen(nl, &tnl)
			nl = &tnl
		}

		if nr.Addable == 0 {
			var tnr Node
			Tempname(&tnr, nr.Type)
			Cgen(nr, &tnr)
			nr = &tnr
		}
	}

	if nl.Addable == 0 {
		Tempname(&tnl, nl.Type)
		Cgen(nl, &tnl)
		nl = &tnl
	}

	// build tree
	// real(l) == real(r) && imag(l) == imag(r)

	var n2 Node
	var n1 Node
	subnode(&n1, &n2, nl)

	var n3 Node
	var n4 Node
	subnode(&n3, &n4, nr)

	var na Node
	na.Op = OANDAND
	var nb Node
	na.Left = &nb
	var nc Node
	na.Right = &nc
	na.Type = Types[TBOOL]

	nb = Node{}
	nb.Op = OEQ
	nb.Left = &n1
	nb.Right = &n3
	nb.Type = Types[TBOOL]

	nc = Node{}
	nc.Op = OEQ
	nc.Left = &n2
	nc.Right = &n4
	nc.Type = Types[TBOOL]

	if op == ONE {
		true_ = !true_
	}

	Bgen(&na, true_, likely, to)
}

// break addable nc-complex into nr-real and ni-imaginary
func subnode(nr *Node, ni *Node, nc *Node) {
	if nc.Addable == 0 {
		Fatal("subnode not addable")
	}

	tc := Simsimtype(nc.Type)
	tc = cplxsubtype(tc)
	t := Types[tc]

	if nc.Op == OLITERAL {
		nodfconst(nr, t, &nc.Val.U.Cval.Real)
		nodfconst(ni, t, &nc.Val.U.Cval.Imag)
		return
	}

	*nr = *nc
	nr.Type = t

	*ni = *nc
	ni.Type = t
	ni.Xoffset += t.Width
}

// generate code res = -nl
func minus(nl *Node, res *Node) {
	var ra Node
	ra.Op = OMINUS
	ra.Left = nl
	ra.Type = nl.Type
	Cgen(&ra, res)
}

// build and execute tree
//	real(res) = -real(nl)
//	imag(res) = -imag(nl)
func complexminus(nl *Node, res *Node) {
	var n1 Node
	var n2 Node
	var n5 Node
	var n6 Node

	subnode(&n1, &n2, nl)
	subnode(&n5, &n6, res)

	minus(&n1, &n5)
	minus(&n2, &n6)
}

// build and execute tree
//	real(res) = real(nl) op real(nr)
//	imag(res) = imag(nl) op imag(nr)
func complexadd(op int, nl *Node, nr *Node, res *Node) {
	var n1 Node
	var n2 Node
	var n3 Node
	var n4 Node
	var n5 Node
	var n6 Node

	subnode(&n1, &n2, nl)
	subnode(&n3, &n4, nr)
	subnode(&n5, &n6, res)

	var ra Node
	ra.Op = uint8(op)
	ra.Left = &n1
	ra.Right = &n3
	ra.Type = n1.Type
	Cgen(&ra, &n5)

	ra = Node{}
	ra.Op = uint8(op)
	ra.Left = &n2
	ra.Right = &n4
	ra.Type = n2.Type
	Cgen(&ra, &n6)
}

// build and execute tree
//	tmp       = real(nl)*real(nr) - imag(nl)*imag(nr)
//	imag(res) = real(nl)*imag(nr) + imag(nl)*real(nr)
//	real(res) = tmp
func complexmul(nl *Node, nr *Node, res *Node) {
	var n1 Node
	var n2 Node
	var n3 Node
	var n4 Node
	var n5 Node
	var n6 Node
	var tmp Node

	subnode(&n1, &n2, nl)
	subnode(&n3, &n4, nr)
	subnode(&n5, &n6, res)
	Tempname(&tmp, n5.Type)

	// real part -> tmp
	var rm1 Node

	rm1.Op = OMUL
	rm1.Left = &n1
	rm1.Right = &n3
	rm1.Type = n1.Type

	var rm2 Node
	rm2.Op = OMUL
	rm2.Left = &n2
	rm2.Right = &n4
	rm2.Type = n2.Type

	var ra Node
	ra.Op = OSUB
	ra.Left = &rm1
	ra.Right = &rm2
	ra.Type = rm1.Type
	Cgen(&ra, &tmp)

	// imag part
	rm1 = Node{}

	rm1.Op = OMUL
	rm1.Left = &n1
	rm1.Right = &n4
	rm1.Type = n1.Type

	rm2 = Node{}
	rm2.Op = OMUL
	rm2.Left = &n2
	rm2.Right = &n3
	rm2.Type = n2.Type

	ra = Node{}
	ra.Op = OADD
	ra.Left = &rm1
	ra.Right = &rm2
	ra.Type = rm1.Type
	Cgen(&ra, &n6)

	// tmp ->real part
	Cgen(&tmp, &n5)
}

func nodfconst(n *Node, t *Type, fval *Mpflt) {
	*n = Node{}
	n.Op = OLITERAL
	n.Addable = 1
	ullmancalc(n)
	n.Val.U.Fval = fval
	n.Val.Ctype = CTFLT
	n.Type = t

	if !Isfloat[t.Etype] {
		Fatal("nodfconst: bad type %v", Tconv(t, 0))
	}
}

func Complexop(n *Node, res *Node) bool {
	if n != nil && n.Type != nil {
		if Iscomplex[n.Type.Etype] {
			goto maybe
		}
	}

	if res != nil && res.Type != nil {
		if Iscomplex[res.Type.Etype] {
			goto maybe
		}
	}

	if n.Op == OREAL || n.Op == OIMAG {
		//dump("\ncomplex-yes", n);
		return true
	}

	//dump("\ncomplex-no", n);
	return false

maybe:
	switch n.Op {
	case OCONV, // implemented ops
		OADD,
		OSUB,
		OMUL,
		OMINUS,
		OCOMPLEX,
		OREAL,
		OIMAG:
		//dump("\ncomplex-yes", n);
		return true

	case ODOT,
		ODOTPTR,
		OINDEX,
		OIND,
		ONAME:
		//dump("\ncomplex-yes", n);
		return true
	}

	//dump("\ncomplex-no", n);
	return false
}

func Complexmove(f *Node, t *Node) {
	if Debug['g'] != 0 {
		Dump("\ncomplexmove-f", f)
		Dump("complexmove-t", t)
	}

	if t.Addable == 0 {
		Fatal("complexmove: to not addable")
	}

	ft := Simsimtype(f.Type)
	tt := Simsimtype(t.Type)
	switch uint32(ft)<<16 | uint32(tt) {
	default:
		Fatal("complexmove: unknown conversion: %v -> %v\n", Tconv(f.Type, 0), Tconv(t.Type, 0))

		// complex to complex move/convert.
	// make f addable.
	// also use temporary if possible stack overlap.
	case TCOMPLEX64<<16 | TCOMPLEX64,
		TCOMPLEX64<<16 | TCOMPLEX128,
		TCOMPLEX128<<16 | TCOMPLEX64,
		TCOMPLEX128<<16 | TCOMPLEX128:
		if f.Addable == 0 || overlap_cplx(f, t) {
			var tmp Node
			Tempname(&tmp, f.Type)
			Complexmove(f, &tmp)
			f = &tmp
		}

		var n1 Node
		var n2 Node
		subnode(&n1, &n2, f)
		var n4 Node
		var n3 Node
		subnode(&n3, &n4, t)

		Cgen(&n1, &n3)
		Cgen(&n2, &n4)
	}
}

func Complexgen(n *Node, res *Node) {
	if Debug['g'] != 0 {
		Dump("\ncomplexgen-n", n)
		Dump("complexgen-res", res)
	}

	for n.Op == OCONVNOP {
		n = n.Left
	}

	// pick off float/complex opcodes
	switch n.Op {
	case OCOMPLEX:
		if res.Addable != 0 {
			var n1 Node
			var n2 Node
			subnode(&n1, &n2, res)
			var tmp Node
			Tempname(&tmp, n1.Type)
			Cgen(n.Left, &tmp)
			Cgen(n.Right, &n2)
			Cgen(&tmp, &n1)
			return
		}

	case OREAL,
		OIMAG:
		nl := n.Left
		if nl.Addable == 0 {
			var tmp Node
			Tempname(&tmp, nl.Type)
			Complexgen(nl, &tmp)
			nl = &tmp
		}

		var n1 Node
		var n2 Node
		subnode(&n1, &n2, nl)
		if n.Op == OREAL {
			Cgen(&n1, res)
			return
		}

		Cgen(&n2, res)
		return
	}

	// perform conversion from n to res
	tl := Simsimtype(res.Type)

	tl = cplxsubtype(tl)
	tr := Simsimtype(n.Type)
	tr = cplxsubtype(tr)
	if tl != tr {
		if n.Addable == 0 {
			var n1 Node
			Tempname(&n1, n.Type)
			Complexmove(n, &n1)
			n = &n1
		}

		Complexmove(n, res)
		return
	}

	if res.Addable == 0 {
		var n1 Node
		Igen(res, &n1, nil)
		Cgen(n, &n1)
		Regfree(&n1)
		return
	}

	if n.Addable != 0 {
		Complexmove(n, res)
		return
	}

	switch n.Op {
	default:
		Dump("complexgen: unknown op", n)
		Fatal("complexgen: unknown op %v", Oconv(int(n.Op), 0))

	case ODOT,
		ODOTPTR,
		OINDEX,
		OIND,
		ONAME, // PHEAP or PPARAMREF var
		OCALLFUNC,
		OCALLMETH,
		OCALLINTER:
		var n1 Node
		Igen(n, &n1, res)

		Complexmove(&n1, res)
		Regfree(&n1)
		return

	case OCONV,
		OADD,
		OSUB,
		OMUL,
		OMINUS,
		OCOMPLEX,
		OREAL,
		OIMAG:
		break
	}

	nl := n.Left
	if nl == nil {
		return
	}
	nr := n.Right

	// make both sides addable in ullman order
	var tnl Node
	if nr != nil {
		if nl.Ullman > nr.Ullman && nl.Addable == 0 {
			Tempname(&tnl, nl.Type)
			Cgen(nl, &tnl)
			nl = &tnl
		}

		if nr.Addable == 0 {
			var tnr Node
			Tempname(&tnr, nr.Type)
			Cgen(nr, &tnr)
			nr = &tnr
		}
	}

	if nl.Addable == 0 {
		Tempname(&tnl, nl.Type)
		Cgen(nl, &tnl)
		nl = &tnl
	}

	switch n.Op {
	default:
		Fatal("complexgen: unknown op %v", Oconv(int(n.Op), 0))

	case OCONV:
		Complexmove(nl, res)

	case OMINUS:
		complexminus(nl, res)

	case OADD,
		OSUB:
		complexadd(int(n.Op), nl, nr, res)

	case OMUL:
		complexmul(nl, nr, res)
	}
}
