mirror of
				https://github.com/golang/go.git
				synced 2025-11-04 02:30:57 +00:00 
			
		
		
		
	cmd/internal/obj/riscv,internal/bytealg: synthesize MIN/MAX/MINU/MAXU instructions
Provide a synthesized version of the MIN/MAX/MINU/MAXU instructions if they're not natively available. This allows these instructions to be used in assembly unconditionally. Use MIN in internal/bytealg.compare. Cq-Include-Trybots: luci.golang.try:gotip-linux-riscv64 Change-Id: I8a5a3a59f0a9205e136fc3d673b23eaf3ca469f8 Reviewed-on: https://go-review.googlesource.com/c/go/+/653295 Reviewed-by: Mark Ryan <markdryan@rivosinc.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Meng Zhuo <mengzhuo1203@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
		
							parent
							
								
									d37624881f
								
							
						
					
					
						commit
						d88f93f720
					
				
					 6 changed files with 339 additions and 14 deletions
				
			
		
							
								
								
									
										16
									
								
								src/cmd/asm/internal/asm/testdata/riscv64.s
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								src/cmd/asm/internal/asm/testdata/riscv64.s
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -376,14 +376,14 @@ start:
 | 
				
			||||||
	CPOPW	X23, X24				// 1b9c2b60
 | 
						CPOPW	X23, X24				// 1b9c2b60
 | 
				
			||||||
	CTZ	X24, X25				// 931c1c60
 | 
						CTZ	X24, X25				// 931c1c60
 | 
				
			||||||
	CTZW	X25, X26				// 1b9d1c60
 | 
						CTZW	X25, X26				// 1b9d1c60
 | 
				
			||||||
	MAX	X26, X28, X29				// b36eae0b
 | 
						MAX	X26, X28, X29				// b36eae0b or b32fae01b30ff041b34eae01b3fedf01b34ede01
 | 
				
			||||||
	MAX	X26, X28				// 336eae0b
 | 
						MAX	X26, X28				// 336eae0b or b32fcd01b30ff041334ecd0133fecf01334ecd01
 | 
				
			||||||
	MAXU	X28, X29, X30				// 33ffce0b
 | 
						MAXU	X28, X29, X30				// 33ffce0b or b3bfce01b30ff04133cfce0133ffef0133cfee01
 | 
				
			||||||
	MAXU	X28, X29				// b3fece0b
 | 
						MAXU	X28, X29				// b3fece0b or b33fde01b30ff041b34ede01b3fedf01b34ede01
 | 
				
			||||||
	MIN	X29, X30, X5				// b342df0b
 | 
						MIN	X29, X30, X5				// b342df0b or b3afee01b30ff041b342df01b3f25f00b3425f00
 | 
				
			||||||
	MIN	X29, X30				// 334fdf0b
 | 
						MIN	X29, X30				// 334fdf0b or b32fdf01b30ff04133cfee0133ffef0133cfee01
 | 
				
			||||||
	MINU	X30, X5, X6				// 33d3e20b
 | 
						MINU	X30, X5, X6				// 33d3e20b or b33f5f00b30ff04133c3e20133f36f0033c36200
 | 
				
			||||||
	MINU	X30, X5					// b3d2e20b
 | 
						MINU	X30, X5					// b3d2e20b or b3bfe201b30ff041b3425f00b3f25f00b3425f00
 | 
				
			||||||
	ORN	X6, X7, X8				// 33e46340 or 1344f3ff33e48300
 | 
						ORN	X6, X7, X8				// 33e46340 or 1344f3ff33e48300
 | 
				
			||||||
	ORN	X6, X7					// b3e36340 or 934ff3ffb3e3f301
 | 
						ORN	X6, X7					// b3e36340 or 934ff3ffb3e3f301
 | 
				
			||||||
	SEXTB	X16, X17				// 93184860
 | 
						SEXTB	X16, X17				// 93184860
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,6 +264,20 @@ func TestBranch(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMinMax(t *testing.T) {
 | 
				
			||||||
 | 
						if runtime.GOARCH != "riscv64" {
 | 
				
			||||||
 | 
							t.Skip("Requires riscv64 to run")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testenv.MustHaveGoBuild(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd := testenv.Command(t, testenv.GoToolPath(t), "test")
 | 
				
			||||||
 | 
						cmd.Dir = "testdata/testminmax"
 | 
				
			||||||
 | 
						if out, err := testenv.CleanCmdEnv(cmd).CombinedOutput(); err != nil {
 | 
				
			||||||
 | 
							t.Errorf("Min max test failed: %v\n%s", err, out)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPCAlign(t *testing.T) {
 | 
					func TestPCAlign(t *testing.T) {
 | 
				
			||||||
	dir := t.TempDir()
 | 
						dir := t.TempDir()
 | 
				
			||||||
	tmpfile := filepath.Join(dir, "x.s")
 | 
						tmpfile := filepath.Join(dir, "x.s")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2785,6 +2785,47 @@ func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// instructionsForMinMax returns the machine instructions for an integer minimum or maximum.
 | 
				
			||||||
 | 
					func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction {
 | 
				
			||||||
 | 
						if buildcfg.GORISCV64 >= 22 {
 | 
				
			||||||
 | 
							// Minimum and maximum instructions are supported natively.
 | 
				
			||||||
 | 
							return []*instruction{ins}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Generate a move for identical inputs.
 | 
				
			||||||
 | 
						if ins.rs1 == ins.rs2 {
 | 
				
			||||||
 | 
							ins.as, ins.rs2, ins.imm = AADDI, obj.REG_NONE, 0
 | 
				
			||||||
 | 
							return []*instruction{ins}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ensure that if one of the source registers is the same as the destination,
 | 
				
			||||||
 | 
						// it is processed first.
 | 
				
			||||||
 | 
						if ins.rs1 == ins.rd {
 | 
				
			||||||
 | 
							ins.rs1, ins.rs2 = ins.rs2, ins.rs1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sltReg1, sltReg2 := ins.rs2, ins.rs1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// MIN -> SLT/SUB/XOR/AND/XOR
 | 
				
			||||||
 | 
						// MAX -> SLT/SUB/XOR/AND/XOR with swapped inputs to SLT
 | 
				
			||||||
 | 
						switch ins.as {
 | 
				
			||||||
 | 
						case AMIN:
 | 
				
			||||||
 | 
							ins.as = ASLT
 | 
				
			||||||
 | 
						case AMAX:
 | 
				
			||||||
 | 
							ins.as, sltReg1, sltReg2 = ASLT, sltReg2, sltReg1
 | 
				
			||||||
 | 
						case AMINU:
 | 
				
			||||||
 | 
							ins.as = ASLTU
 | 
				
			||||||
 | 
						case AMAXU:
 | 
				
			||||||
 | 
							ins.as, sltReg1, sltReg2 = ASLTU, sltReg2, sltReg1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return []*instruction{
 | 
				
			||||||
 | 
							&instruction{as: ins.as, rs1: sltReg1, rs2: sltReg2, rd: REG_TMP},
 | 
				
			||||||
 | 
							&instruction{as: ASUB, rs1: REG_ZERO, rs2: REG_TMP, rd: REG_TMP},
 | 
				
			||||||
 | 
							&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
 | 
				
			||||||
 | 
							&instruction{as: AAND, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
 | 
				
			||||||
 | 
							&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rd, rd: ins.rd},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// instructionsForProg returns the machine instructions for an *obj.Prog.
 | 
					// instructionsForProg returns the machine instructions for an *obj.Prog.
 | 
				
			||||||
func instructionsForProg(p *obj.Prog) []*instruction {
 | 
					func instructionsForProg(p *obj.Prog) []*instruction {
 | 
				
			||||||
	ins := instructionForProg(p)
 | 
						ins := instructionForProg(p)
 | 
				
			||||||
| 
						 | 
					@ -3034,6 +3075,9 @@ func instructionsForProg(p *obj.Prog) []*instruction {
 | 
				
			||||||
		ins.as = AXOR
 | 
							ins.as = AXOR
 | 
				
			||||||
		inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
 | 
							inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case AMIN, AMAX, AMINU, AMAXU:
 | 
				
			||||||
 | 
							inss = instructionsForMinMax(p, ins)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case AVSETVLI, AVSETIVLI:
 | 
						case AVSETVLI, AVSETIVLI:
 | 
				
			||||||
		ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
 | 
							ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
 | 
				
			||||||
		vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset)
 | 
							vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										140
									
								
								src/cmd/internal/obj/riscv/testdata/testminmax/minmax_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/cmd/internal/obj/riscv/testdata/testminmax/minmax_test.go
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,140 @@
 | 
				
			||||||
 | 
					// Copyright 2025 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:build riscv64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package testminmax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func testMIN1(a int64) (r int64)
 | 
				
			||||||
 | 
					func testMIN2(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMIN3(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMIN4(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMAX1(a int64) (r int64)
 | 
				
			||||||
 | 
					func testMAX2(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMAX3(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMAX4(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMINU1(a int64) (r int64)
 | 
				
			||||||
 | 
					func testMINU2(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMINU3(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMINU4(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMAXU1(a int64) (r int64)
 | 
				
			||||||
 | 
					func testMAXU2(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMAXU3(a, b int64) (r int64)
 | 
				
			||||||
 | 
					func testMAXU4(a, b int64) (r int64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMin(t *testing.T) {
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							a    int64
 | 
				
			||||||
 | 
							b    int64
 | 
				
			||||||
 | 
							want int64
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{1, 2, 1},
 | 
				
			||||||
 | 
							{2, 1, 1},
 | 
				
			||||||
 | 
							{2, 2, 2},
 | 
				
			||||||
 | 
							{1, -1, -1},
 | 
				
			||||||
 | 
							{-1, 1, -1},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							if got := testMIN1(test.a); got != test.a {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMIN1 %v = %v, want %v", test.a, got, test.a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMIN2(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMIN2 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMIN3(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMIN3 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMIN4(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMIN4 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMax(t *testing.T) {
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							a    int64
 | 
				
			||||||
 | 
							b    int64
 | 
				
			||||||
 | 
							want int64
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{1, 2, 2},
 | 
				
			||||||
 | 
							{2, 1, 2},
 | 
				
			||||||
 | 
							{2, 2, 2},
 | 
				
			||||||
 | 
							{1, -1, 1},
 | 
				
			||||||
 | 
							{-1, 1, 1},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							if got := testMAX1(test.a); got != test.a {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMAX1 %v = %v, want %v", test.a, got, test.a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMAX2(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMAX2 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMAX3(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMAX3 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMAX4(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMAX4 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMinU(t *testing.T) {
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							a    int64
 | 
				
			||||||
 | 
							b    int64
 | 
				
			||||||
 | 
							want int64
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{1, 2, 1},
 | 
				
			||||||
 | 
							{2, 1, 1},
 | 
				
			||||||
 | 
							{2, 2, 2},
 | 
				
			||||||
 | 
							{1, -1, 1},
 | 
				
			||||||
 | 
							{-1, 1, 1},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							if got := testMINU1(test.a); got != test.a {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMINU1 %v = %v, want %v", test.a, got, test.a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMINU2(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMINU2 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMINU3(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMINU3 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMINU4(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMINU4 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMaxU(t *testing.T) {
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							a    int64
 | 
				
			||||||
 | 
							b    int64
 | 
				
			||||||
 | 
							want int64
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{1, 2, 2},
 | 
				
			||||||
 | 
							{2, 1, 2},
 | 
				
			||||||
 | 
							{2, 2, 2},
 | 
				
			||||||
 | 
							{1, -1, -1},
 | 
				
			||||||
 | 
							{-1, 1, -1},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							if got := testMAXU1(test.a); got != test.a {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMAXU1 %v = %v, want %v", test.a, got, test.a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMAXU2(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMAXU2 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMAXU3(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMAXU3 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if got := testMAXU4(test.a, test.b); got != test.want {
 | 
				
			||||||
 | 
								t.Errorf("Assembly testMAXU4 %v, %v = %v, want %v", test.a, test.b, got, test.want)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										131
									
								
								src/cmd/internal/obj/riscv/testdata/testminmax/minmax_test.s
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								src/cmd/internal/obj/riscv/testdata/testminmax/minmax_test.s
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,131 @@
 | 
				
			||||||
 | 
					// Copyright 2025 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:build riscv64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "textflag.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMIN1(a int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMIN1(SB),NOSPLIT,$0-16
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MIN	X5, X5, X6
 | 
				
			||||||
 | 
						MOV	X6, r+8(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMIN2(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMIN2(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MIN	X5, X6, X6
 | 
				
			||||||
 | 
						MOV	X6, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMIN3(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMIN3(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MIN	X6, X5, X5
 | 
				
			||||||
 | 
						MOV	X5, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMIN4(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMIN4(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MIN	X5, X6, X7
 | 
				
			||||||
 | 
						MOV	X7, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMAX1(a int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMAX1(SB),NOSPLIT,$0-16
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MAX	X5, X5, X6
 | 
				
			||||||
 | 
						MOV	X6, r+8(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMAX2(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMAX2(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MAX	X5, X6, X6
 | 
				
			||||||
 | 
						MOV	X6, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMAX3(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMAX3(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MAX	X6, X5, X5
 | 
				
			||||||
 | 
						MOV	X5, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMAX4(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMAX4(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MAX	X5, X6, X7
 | 
				
			||||||
 | 
						MOV	X7, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMINU1(a int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMINU1(SB),NOSPLIT,$0-16
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MINU	X5, X5, X6
 | 
				
			||||||
 | 
						MOV	X6, r+8(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMINU2(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMINU2(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MINU	X5, X6, X6
 | 
				
			||||||
 | 
						MOV	X6, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMINU3(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMINU3(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MINU	X6, X5, X5
 | 
				
			||||||
 | 
						MOV	X5, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMINU4(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMINU4(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MINU	X5, X6, X7
 | 
				
			||||||
 | 
						MOV	X7, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMAXU1(a int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMAXU1(SB),NOSPLIT,$0-16
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MAXU	X5, X5, X6
 | 
				
			||||||
 | 
						MOV	X6, r+8(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMAXU2(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMAXU2(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MAXU	X5, X6, X6
 | 
				
			||||||
 | 
						MOV	X6, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMAXU3(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMAXU3(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MAXU	X6, X5, X5
 | 
				
			||||||
 | 
						MOV	X5, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// func testMAXU4(a, b int64) (r int64)
 | 
				
			||||||
 | 
					TEXT ·testMAXU4(SB),NOSPLIT,$0-24
 | 
				
			||||||
 | 
						MOV	a+0(FP), X5
 | 
				
			||||||
 | 
						MOV	b+8(FP), X6
 | 
				
			||||||
 | 
						MAXU	X5, X6, X7
 | 
				
			||||||
 | 
						MOV	X7, r+16(FP)
 | 
				
			||||||
 | 
						RET
 | 
				
			||||||
| 
						 | 
					@ -28,15 +28,11 @@ TEXT runtime·cmpstring<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-40
 | 
				
			||||||
// X11 length of a
 | 
					// X11 length of a
 | 
				
			||||||
// X12 points to start of b
 | 
					// X12 points to start of b
 | 
				
			||||||
// X13 length of b
 | 
					// X13 length of b
 | 
				
			||||||
// for non-regabi X14 points to the address to store the return value (-1/0/1)
 | 
					// return value in X10 (-1/0/1)
 | 
				
			||||||
// for regabi the return value in X10
 | 
					 | 
				
			||||||
TEXT compare<>(SB),NOSPLIT|NOFRAME,$0
 | 
					TEXT compare<>(SB),NOSPLIT|NOFRAME,$0
 | 
				
			||||||
	BEQ	X10, X12, cmp_len
 | 
						BEQ	X10, X12, cmp_len
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MOV	X11, X5
 | 
						MIN	X11, X13, X5
 | 
				
			||||||
	BGE	X13, X5, use_a_len // X5 = min(len(a), len(b))
 | 
					 | 
				
			||||||
	MOV	X13, X5
 | 
					 | 
				
			||||||
use_a_len:
 | 
					 | 
				
			||||||
	BEQZ	X5, cmp_len
 | 
						BEQZ	X5, cmp_len
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MOV	$32, X6
 | 
						MOV	$32, X6
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue