Source file src/math/big/internal/asmgen/s390x.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package asmgen
     6  
     7  var ArchS390X = &Arch{
     8  	Name:          "s390x",
     9  	WordBits:      64,
    10  	WordBytes:     8,
    11  	CarrySafeLoop: true,
    12  
    13  	regs: []string{
    14  		// R0 is 0 by convention in this code (see setup).
    15  		// R10 is the assembler/linker temporary.
    16  		// R11 is a second assembler/linker temporary, for wide multiply.
    17  		// We allow allocating R10 and R11 so that we can use them as
    18  		// direct multiplication targets while tracking whether they're in use.
    19  		// R13 is g.
    20  		// R14 is LR.
    21  		// R15 is SP.
    22  		"R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9",
    23  		"R10", "R11", "R12",
    24  	},
    25  	reg0:       "R0",
    26  	regTmp:     "R10",
    27  	setup:      s390xSetup,
    28  	maxColumns: 2,
    29  	op3:        s390xOp3,
    30  	hint:       s390xHint,
    31  
    32  	// Instruction reference: chapter 7 of
    33  	// https://www.ibm.com/docs/en/SSQ2R2_15.0.0/com.ibm.tpf.toolkit.hlasm.doc/dz9zr006.pdf
    34  
    35  	mov:      "MOVD",
    36  	adds:     "ADDC", // ADD is an alias for ADDC, sets carry
    37  	adcs:     "ADDE",
    38  	subs:     "SUBC", // SUB is an alias for SUBC, sets carry
    39  	sbcs:     "SUBE",
    40  	mulWideF: s390MulWide,
    41  	lsh:      "SLD",
    42  	rsh:      "SRD",
    43  	and:      "AND",
    44  	or:       "OR",
    45  	xor:      "XOR",
    46  	neg:      "NEG",
    47  	lea:      "LAY", // LAY because LA only accepts positive offsets
    48  
    49  	jmpZero:    "CMPBEQ %s, $0, %s",
    50  	jmpNonZero: "CMPBNE %s, $0, %s",
    51  }
    52  
    53  func s390xSetup(f *Func) {
    54  	a := f.Asm
    55  	if f.Name == "addVV" || f.Name == "subVV" {
    56  		// S390x, unlike every other system, has vector instructions
    57  		// that can propagate carry bits during parallel adds (VACC).
    58  		// Instead of trying to generate that for this one system,
    59  		// jump to the hand-written code in arithvec_s390x.s.
    60  		a.Printf("\tMOVB ·hasVX(SB), R1\n")
    61  		a.Printf("\tCMPBEQ R1, $0, novec\n")
    62  		a.Printf("\tJMP ·%svec(SB)\n", f.Name)
    63  		a.Printf("novec:\n")
    64  	}
    65  	a.Printf("\tMOVD $0, R0\n")
    66  }
    67  
    68  func s390xOp3(name string) bool {
    69  	if name == "AND" { // AND with immediate only takes imm, reg; not imm, reg, reg.
    70  		return false
    71  	}
    72  	return true
    73  }
    74  
    75  func s390xHint(_ *Asm, h Hint) string {
    76  	switch h {
    77  	case HintMulSrc:
    78  		return "R11"
    79  	case HintMulHi:
    80  		return "R10"
    81  	}
    82  	return ""
    83  }
    84  
    85  func s390MulWide(a *Asm, src1, src2, dstlo, dsthi Reg) {
    86  	if src1.name != "R11" && src2.name != "R11" {
    87  		a.Fatalf("mulWide src1 or src2 must be R11")
    88  	}
    89  	if dstlo.name != "R11" {
    90  		a.Fatalf("mulWide dstlo must be R11")
    91  	}
    92  	if dsthi.name != "R10" {
    93  		a.Fatalf("mulWide dsthi must be R10")
    94  	}
    95  	src := src1
    96  	if src.name == "R11" {
    97  		src = src2
    98  	}
    99  	a.Printf("\tMLGR %s, R10\n", src)
   100  }
   101  

View as plain text