Source file src/cmd/asm/internal/arch/loong64.go

     1  // Copyright 2022 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  // This file encapsulates some of the odd characteristics of the
     6  // Loong64 (LoongArch64) instruction set, to minimize its interaction
     7  // with the core of the assembler.
     8  
     9  package arch
    10  
    11  import (
    12  	"cmd/internal/obj"
    13  	"cmd/internal/obj/loong64"
    14  	"errors"
    15  	"fmt"
    16  )
    17  
    18  func jumpLoong64(word string) bool {
    19  	switch word {
    20  	case "BEQ", "BFPF", "BFPT", "BLTZ", "BGEZ", "BLEZ", "BGTZ", "BLT", "BLTU", "JIRL", "BNE", "BGE", "BGEU", "JMP", "JAL", "CALL":
    21  		return true
    22  	}
    23  	return false
    24  }
    25  
    26  // IsLoong64MUL reports whether the op (as defined by an loong64.A* constant) is
    27  // one of the MUL/DIV/REM instructions that require special handling.
    28  func IsLoong64MUL(op obj.As) bool {
    29  	switch op {
    30  	case loong64.AMUL, loong64.AMULU, loong64.AMULV, loong64.AMULVU,
    31  		loong64.ADIV, loong64.ADIVU, loong64.ADIVV, loong64.ADIVVU,
    32  		loong64.AREM, loong64.AREMU, loong64.AREMV, loong64.AREMVU:
    33  		return true
    34  	}
    35  	return false
    36  }
    37  
    38  // IsLoong64RDTIME reports whether the op (as defined by an loong64.A*
    39  // constant) is one of the RDTIMELW/RDTIMEHW/RDTIMED instructions that
    40  // require special handling.
    41  func IsLoong64RDTIME(op obj.As) bool {
    42  	switch op {
    43  	case loong64.ARDTIMELW, loong64.ARDTIMEHW, loong64.ARDTIMED:
    44  		return true
    45  	}
    46  	return false
    47  }
    48  
    49  func IsLoong64PRELD(op obj.As) bool {
    50  	switch op {
    51  	case loong64.APRELD, loong64.APRELDX:
    52  		return true
    53  	}
    54  	return false
    55  }
    56  
    57  func IsLoong64AMO(op obj.As) bool {
    58  	return loong64.IsAtomicInst(op)
    59  }
    60  
    61  var loong64ElemExtMap = map[string]int16{
    62  	"B":  loong64.ARNG_B,
    63  	"H":  loong64.ARNG_H,
    64  	"W":  loong64.ARNG_W,
    65  	"V":  loong64.ARNG_V,
    66  	"BU": loong64.ARNG_BU,
    67  	"HU": loong64.ARNG_HU,
    68  	"WU": loong64.ARNG_WU,
    69  	"VU": loong64.ARNG_VU,
    70  }
    71  
    72  var loong64LsxArngExtMap = map[string]int16{
    73  	"B16": loong64.ARNG_16B,
    74  	"H8":  loong64.ARNG_8H,
    75  	"W4":  loong64.ARNG_4W,
    76  	"V2":  loong64.ARNG_2V,
    77  }
    78  
    79  var loong64LasxArngExtMap = map[string]int16{
    80  	"B32": loong64.ARNG_32B,
    81  	"H16": loong64.ARNG_16H,
    82  	"W8":  loong64.ARNG_8W,
    83  	"V4":  loong64.ARNG_4V,
    84  	"Q2":  loong64.ARNG_2Q,
    85  }
    86  
    87  // Loong64RegisterExtension constructs an Loong64 register with extension or arrangement.
    88  func Loong64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
    89  	var ok bool
    90  	var arng_type int16
    91  	var simd_type int16
    92  
    93  	switch {
    94  	case reg >= loong64.REG_V0 && reg <= loong64.REG_V31:
    95  		simd_type = loong64.LSX
    96  	case reg >= loong64.REG_X0 && reg <= loong64.REG_X31:
    97  		simd_type = loong64.LASX
    98  	default:
    99  		return errors.New("Loong64 extension: invalid LSX/LASX register: " + fmt.Sprintf("%d", reg))
   100  	}
   101  
   102  	if isIndex {
   103  		arng_type, ok = loong64ElemExtMap[ext]
   104  		if !ok {
   105  			return errors.New("Loong64 extension: invalid LSX/LASX arrangement type: " + ext)
   106  		}
   107  
   108  		a.Reg = loong64.REG_ELEM
   109  		a.Reg += ((reg & loong64.EXT_REG_MASK) << loong64.EXT_REG_SHIFT)
   110  		a.Reg += ((arng_type & loong64.EXT_TYPE_MASK) << loong64.EXT_TYPE_SHIFT)
   111  		a.Reg += ((simd_type & loong64.EXT_SIMDTYPE_MASK) << loong64.EXT_SIMDTYPE_SHIFT)
   112  		a.Index = num
   113  	} else {
   114  		switch simd_type {
   115  		case loong64.LSX:
   116  			arng_type, ok = loong64LsxArngExtMap[ext]
   117  			if !ok {
   118  				return errors.New("Loong64 extension: invalid LSX arrangement type: " + ext)
   119  			}
   120  
   121  		case loong64.LASX:
   122  			arng_type, ok = loong64LasxArngExtMap[ext]
   123  			if !ok {
   124  				return errors.New("Loong64 extension: invalid LASX arrangement type: " + ext)
   125  			}
   126  		}
   127  
   128  		a.Reg = loong64.REG_ARNG
   129  		a.Reg += ((reg & loong64.EXT_REG_MASK) << loong64.EXT_REG_SHIFT)
   130  		a.Reg += ((arng_type & loong64.EXT_TYPE_MASK) << loong64.EXT_TYPE_SHIFT)
   131  		a.Reg += ((simd_type & loong64.EXT_SIMDTYPE_MASK) << loong64.EXT_SIMDTYPE_SHIFT)
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func loong64RegisterNumber(name string, n int16) (int16, bool) {
   138  	switch name {
   139  	case "F":
   140  		if 0 <= n && n <= 31 {
   141  			return loong64.REG_F0 + n, true
   142  		}
   143  	case "FCSR":
   144  		if 0 <= n && n <= 31 {
   145  			return loong64.REG_FCSR0 + n, true
   146  		}
   147  	case "FCC":
   148  		if 0 <= n && n <= 31 {
   149  			return loong64.REG_FCC0 + n, true
   150  		}
   151  	case "R":
   152  		if 0 <= n && n <= 31 {
   153  			return loong64.REG_R0 + n, true
   154  		}
   155  	case "V":
   156  		if 0 <= n && n <= 31 {
   157  			return loong64.REG_V0 + n, true
   158  		}
   159  	case "X":
   160  		if 0 <= n && n <= 31 {
   161  			return loong64.REG_X0 + n, true
   162  		}
   163  	}
   164  	return 0, false
   165  }
   166  

View as plain text