summaryrefslogtreecommitdiff
path: root/libgo/go/reflect/makefuncgo_s390x.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/reflect/makefuncgo_s390x.go')
-rw-r--r--libgo/go/reflect/makefuncgo_s390x.go436
1 files changed, 0 insertions, 436 deletions
diff --git a/libgo/go/reflect/makefuncgo_s390x.go b/libgo/go/reflect/makefuncgo_s390x.go
deleted file mode 100644
index 6e510156b34..00000000000
--- a/libgo/go/reflect/makefuncgo_s390x.go
+++ /dev/null
@@ -1,436 +0,0 @@
-// 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.
-
-// MakeFunc s390x implementation.
-
-package reflect
-
-import "unsafe"
-
-// Convenience types and constants.
-const s390x_arch_stack_slot_align uintptr = 8
-const s390x_num_gr = 5
-const s390x_num_fr = 4
-
-type s390x_arch_gr_t uint64
-type s390x_arch_fr_t uint64
-
-// The assembler stub will pass a pointer to this structure.
-// This will come in holding all the registers that might hold
-// function parameters. On return we will set the registers that
-// might hold result values.
-type s390x_regs struct {
- r2 s390x_arch_gr_t
- r3 s390x_arch_gr_t
- r4 s390x_arch_gr_t
- r5 s390x_arch_gr_t
- r6 s390x_arch_gr_t
- stack_args s390x_arch_gr_t
- f0 s390x_arch_fr_t
- f2 s390x_arch_fr_t
- f4 s390x_arch_fr_t
- f6 s390x_arch_fr_t
-}
-
-// Argument classifications that arise for Go types.
-type s390x_arg_t int
-
-const (
- s390x_general_reg s390x_arg_t = iota
- s390x_float_reg
- // Argument passed as a pointer to an in-memory value.
- s390x_mem_ptr
- s390x_empty
-)
-
-// s390xClassifyParameter returns the register class needed to
-// pass the value of type TYP. s390x_empty means the register is
-// not used. The second and third return values are the offset of
-// an rtype parameter passed in a register (second) or stack slot
-// (third).
-func s390xClassifyParameter(typ *rtype) (s390x_arg_t, uintptr, uintptr) {
- offset := s390x_arch_stack_slot_align - typ.Size()
- switch typ.Kind() {
- default:
- panic("internal error--unknown kind in s390xClassifyParameter")
- case Bool, Int, Int8, Int16, Int32, Uint, Uint8, Uint16, Uint32:
- return s390x_general_reg, offset, offset
- case Int64, Uint64, Uintptr, Chan, Func, Map, Ptr, UnsafePointer:
- return s390x_general_reg, 0, 0
- case Float32, Float64:
- return s390x_float_reg, 0, offset
- case Complex64, Complex128:
- // Complex numbers are passed by reference.
- return s390x_mem_ptr, 0, 0
- case Array, Struct:
- var ityp *rtype
- var length int
-
- if typ.Size() == 0 {
- return s390x_empty, 0, 0
- }
- switch typ.Size() {
- default:
- // Pointer to memory.
- return s390x_mem_ptr, 0, 0
- case 1, 2:
- // Pass in an integer register.
- return s390x_general_reg, offset, offset
-
- case 4, 8:
- // See below.
- }
- if typ.Kind() == Array {
- atyp := (*arrayType)(unsafe.Pointer(typ))
- length = atyp.Len()
- ityp = atyp.elem
- } else {
- styp := (*structType)(unsafe.Pointer(typ))
- length = len(styp.fields)
- ityp = styp.fields[0].typ
- }
- if length == 1 {
- class, off_reg, off_slot := s390xClassifyParameter(ityp)
- if class == s390x_float_reg {
- // The array (stored in a structure) or struct
- // is "equivalent to a floating point type" as
- // defined in the S390x Abi. Note that this
- // can only be the case in the cases 4 and 8 of
- // the switch above.
- return s390x_float_reg, off_reg, off_slot
- }
- }
- // Otherwise pass in an integer register.
- switch typ.Size() {
- case 4, 8:
- return s390x_general_reg, offset, offset
- default:
- return s390x_general_reg, 0, 0
- }
- case Interface, Slice, String:
- return s390x_mem_ptr, 0, 0
- }
-}
-
-// s390xClassifyReturn returns the register classes needed to
-// return the value of type TYP. s390_empty means the register is
-// not used. The second value is the offset of an rtype return
-// parameter if stored in a register.
-func s390xClassifyReturn(typ *rtype) (s390x_arg_t, uintptr) {
- offset := s390x_arch_stack_slot_align - typ.Size()
- switch typ.Kind() {
- default:
- panic("internal error--unknown kind in s390xClassifyReturn")
- case Bool, Int, Int8, Int16, Int32, Int64,
- Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
-
- return s390x_general_reg, offset
- case Chan, Func, Map, Ptr, UnsafePointer:
- return s390x_general_reg, 0
- case Float32, Float64:
- return s390x_float_reg, 0
- case Complex64, Complex128:
- return s390x_mem_ptr, 0
- case Interface, Slice, String:
- return s390x_mem_ptr, 0
- case Array, Struct:
- if typ.size == 0 {
- return s390x_empty, 0
- }
- // No optimization is done for returned structures and arrays.
- return s390x_mem_ptr, 0
- }
-}
-
-// Given a value of type *rtype left aligned in an unsafe.Pointer,
-// reload the value so that it can be stored in a general or
-// floating point register. For general registers the value is
-// sign extend and right aligned.
-func s390xReloadForRegister(typ *rtype, w uintptr, offset uintptr) uintptr {
- var do_sign_extend bool = false
- var gr s390x_arch_gr_t
-
- switch typ.Kind() {
- case Int, Int8, Int16, Int32, Int64:
- do_sign_extend = true
- default:
- // Handle all other cases in the next switch.
- }
- switch typ.size {
- case 1:
- if do_sign_extend == true {
- se := int64(*(*int8)(unsafe.Pointer(&w)))
- gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
- } else {
- e := int64(*(*uint8)(unsafe.Pointer(&w)))
- gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
- }
- case 2:
- if do_sign_extend == true {
- se := int64(*(*int16)(unsafe.Pointer(&w)))
- gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
- } else {
- e := int64(*(*uint16)(unsafe.Pointer(&w)))
- gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
- }
- case 4:
- if do_sign_extend == true {
- se := int64(*(*int32)(unsafe.Pointer(&w)))
- gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&se))
- } else {
- e := int64(*(*uint32)(unsafe.Pointer(&w)))
- gr = *(*s390x_arch_gr_t)(unsafe.Pointer(&e))
- }
- default:
- panic("reflect: bad size in s390xReloadForRegister")
- }
-
- return *(*uintptr)(unsafe.Pointer(&gr))
-}
-
-// MakeFuncStubGo implements the s390x calling convention for
-// MakeFunc. This should not be called. It is exported so that
-// assembly code can call it.
-func S390xMakeFuncStubGo(regs *s390x_regs, c *makeFuncImpl) {
- ftyp := c.typ
- gr := 0
- fr := 0
- ap := uintptr(regs.stack_args)
-
- // See if the result requires a struct. If it does, the first
- // parameter is a pointer to the struct.
- var ret_class s390x_arg_t
- var ret_off_reg uintptr
- var ret_type *rtype
-
- switch len(ftyp.out) {
- case 0:
- ret_type = nil
- ret_class, ret_off_reg = s390x_empty, 0
- case 1:
- ret_type = ftyp.out[0]
- ret_class, ret_off_reg = s390xClassifyReturn(ret_type)
- default:
- ret_type = nil
- ret_class, ret_off_reg = s390x_mem_ptr, 0
- }
- in := make([]Value, 0, len(ftyp.in))
- if ret_class == s390x_mem_ptr {
- // We are returning a value in memory, which means
- // that the first argument is a hidden parameter
- // pointing to that return area.
- gr++
- }
-
-argloop:
- for _, rt := range ftyp.in {
- class, off_reg, off_slot := s390xClassifyParameter(rt)
- fl := flag(rt.Kind())
- switch class {
- case s390x_empty:
- v := Value{rt, nil, fl | flagIndir}
- in = append(in, v)
- continue argloop
- case s390x_general_reg:
- // Values stored in a general register are right
- // aligned.
- if gr < s390x_num_gr {
- val := s390x_general_reg_val(regs, gr)
- iw := unsafe.Pointer(val)
- k := rt.Kind()
- if k != Ptr && k != UnsafePointer {
- ix := uintptr(unsafe.Pointer(&val))
- ix += off_reg
- iw = unsafe.Pointer(ix)
- fl |= flagIndir
- }
- v := Value{rt, iw, fl}
- in = append(in, v)
- gr++
- } else {
- in, ap = s390x_add_stackreg(
- in, ap, rt, off_slot)
- }
- continue argloop
- case s390x_float_reg:
- // In a register, floats are left aligned, but in a
- // stack slot they are right aligned.
- if fr < s390x_num_fr {
- val := s390x_float_reg_val(regs, fr)
- ix := uintptr(unsafe.Pointer(&val))
- v := Value{
- rt, unsafe.Pointer(unsafe.Pointer(ix)),
- fl | flagIndir,
- }
- in = append(in, v)
- fr++
- } else {
- in, ap = s390x_add_stackreg(
- in, ap, rt, off_slot)
- }
- continue argloop
- case s390x_mem_ptr:
- if gr < s390x_num_gr {
- // Register holding a pointer to memory.
- val := s390x_general_reg_val(regs, gr)
- v := Value{
- rt, unsafe.Pointer(val), fl | flagIndir}
- in = append(in, v)
- gr++
- } else {
- // Stack slot holding a pointer to memory.
- in, ap = s390x_add_memarg(in, ap, rt)
- }
- continue argloop
- }
- panic("reflect: argtype not handled in MakeFunc:argloop")
- }
-
- // All the real arguments have been found and turned into
- // Values. Call the real function.
-
- out := c.call(in)
-
- if len(out) != len(ftyp.out) {
- panic("reflect: wrong return count from function created by MakeFunc")
- }
-
- for i, typ := range ftyp.out {
- v := out[i]
- if v.typ != typ {
- panic(
- "reflect: function created by MakeFunc using " +
- funcName(c.fn) + " returned wrong type: have " +
- out[i].typ.String() + " for " + typ.String())
- }
- if v.flag&flagRO != 0 {
- panic(
- "reflect: function created by MakeFunc using " +
- funcName(c.fn) + " returned value obtained " +
- "from unexported field")
- }
- }
-
- switch ret_class {
- case s390x_general_reg, s390x_float_reg:
- // Single return value in a general or floating point register.
- v := out[0]
- var w uintptr
- switch v.Kind() {
- case Ptr, UnsafePointer, Chan, Func, Map:
- w = uintptr(v.pointer())
- default:
- memmove(unsafe.Pointer(&w), v.ptr, v.typ.size)
- if ret_off_reg != 0 {
- w = s390xReloadForRegister(
- ret_type, w, ret_off_reg)
- }
- }
- if ret_class == s390x_float_reg {
- regs.f0 = s390x_arch_fr_t(w)
- } else {
- regs.r2 = s390x_arch_gr_t(w)
- }
-
- case s390x_mem_ptr:
- // The address of the memory area was passed as a hidden
- // parameter in %r2. Multiple return values are always returned
- // in an in-memory structure.
- ptr := unsafe.Pointer(uintptr(regs.r2))
- off := uintptr(0)
- for i, typ := range ftyp.out {
- v := out[i]
- off = align(off, uintptr(typ.fieldAlign))
- addr := unsafe.Pointer(uintptr(ptr) + off)
- if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
- *(*unsafe.Pointer)(addr) = v.ptr
- } else {
- memmove(addr, v.ptr, typ.size)
- }
- off += typ.size
- }
-
- case s390x_empty:
- }
-
- return
-}
-
-// The s390x_add_stackreg function adds an argument passed on the
-// stack that could be passed in a register.
-func s390x_add_stackreg(in []Value, ap uintptr, rt *rtype, offset uintptr) ([]Value, uintptr) {
- // If we're not already at the beginning of a stack slot, round up to
- // the beginning of the next one.
- ap = align(ap, s390x_arch_stack_slot_align)
- // If offset is > 0, the data is right aligned on the stack slot.
- ap += offset
-
- // We have to copy the argument onto the heap in case the
- // function hangs onto the reflect.Value we pass it.
- p := unsafe_New(rt)
- memmove(p, unsafe.Pointer(ap), rt.size)
-
- v := Value{rt, p, flag(rt.Kind()) | flagIndir}
- in = append(in, v)
- ap += rt.size
- ap = align(ap, s390x_arch_stack_slot_align)
-
- return in, ap
-}
-
-// The s390x_add_memarg function adds an argument passed in memory.
-func s390x_add_memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) {
- // If we're not already at the beginning of a stack slot,
- // round up to the beginning of the next one.
- ap = align(ap, s390x_arch_stack_slot_align)
-
- // We have to copy the argument onto the heap in case the
- // function hangs onto the reflect.Value we pass it.
- p := unsafe_New(rt)
- memmove(p, *(*unsafe.Pointer)(unsafe.Pointer(ap)), rt.size)
-
- v := Value{rt, p, flag(rt.Kind()) | flagIndir}
- in = append(in, v)
- ap += s390x_arch_stack_slot_align
-
- return in, ap
-}
-
-// The s390x_general_reg_val function returns the value of integer register GR.
-func s390x_general_reg_val(regs *s390x_regs, gr int) uintptr {
- var r s390x_arch_gr_t
- switch gr {
- case 0:
- r = regs.r2
- case 1:
- r = regs.r3
- case 2:
- r = regs.r4
- case 3:
- r = regs.r5
- case 4:
- r = regs.r6
- default:
- panic("s390x_general_reg_val: bad integer register")
- }
- return uintptr(r)
-}
-
-// The s390x_float_reg_val function returns the value of float register FR.
-func s390x_float_reg_val(regs *s390x_regs, fr int) uintptr {
- var r s390x_arch_fr_t
- switch fr {
- case 0:
- r = regs.f0
- case 1:
- r = regs.f2
- case 2:
- r = regs.f4
- case 3:
- r = regs.f6
- default:
- panic("s390x_float_reg_val: bad floating point register")
- }
- return uintptr(r)
-}