Source file src/cmd/vendor/golang.org/x/arch/loong64/loong64asm/inst.go

     1  // Copyright 2024 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 loong64asm
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  )
    11  
    12  // An Inst is a single instruction.
    13  type Inst struct {
    14  	Op   Op     // Opcode mnemonic
    15  	Enc  uint32 // Raw encoding bits.
    16  	Args Args   // Instruction arguments, in Loong64 manual order.
    17  }
    18  
    19  func (i Inst) String() string {
    20  	var op string = i.Op.String()
    21  	var args []string
    22  
    23  	for _, arg := range i.Args {
    24  		if arg == nil {
    25  			break
    26  		}
    27  		args = append(args, arg.String())
    28  	}
    29  
    30  	switch i.Op {
    31  	case OR:
    32  		if i.Args[2].(Reg) == R0 {
    33  			op = "move"
    34  			args = args[0:2]
    35  		}
    36  
    37  	case ANDI:
    38  		if i.Args[0].(Reg) == R0 && i.Args[1].(Reg) == R0 {
    39  			return "nop"
    40  		}
    41  
    42  	case JIRL:
    43  		if i.Args[0].(Reg) == R0 && i.Args[1].(Reg) == R1 && i.Args[2].(OffsetSimm).Imm == 0 {
    44  			return "ret"
    45  		} else if i.Args[0].(Reg) == R0 && i.Args[2].(OffsetSimm).Imm == 0 {
    46  			return "jr " + args[1]
    47  		}
    48  
    49  	case BLT:
    50  		if i.Args[0].(Reg) == R0 {
    51  			op = "bgtz"
    52  			args = args[1:]
    53  		} else if i.Args[1].(Reg) == R0 {
    54  			op = "bltz"
    55  			args = append(args[:1], args[2:]...)
    56  		}
    57  
    58  	case BGE:
    59  		if i.Args[0].(Reg) == R0 {
    60  			op = "blez"
    61  			args = args[1:]
    62  		} else if i.Args[1].(Reg) == R0 {
    63  			op = "bgez"
    64  			args = append(args[:1], args[2:]...)
    65  		}
    66  	}
    67  
    68  	if len(args) == 0 {
    69  		return op
    70  	} else {
    71  		return op + " " + strings.Join(args, ", ")
    72  	}
    73  }
    74  
    75  // An Op is an Loong64 opcode.
    76  type Op uint16
    77  
    78  // NOTE: The actual Op values are defined in tables.go.
    79  // They are chosen to simplify instruction decoding and
    80  // are not a dense packing from 0 to N, although the
    81  // density is high, probably at least 90%.
    82  func (op Op) String() string {
    83  	if (op >= Op(len(opstr))) || (opstr[op] == "") {
    84  		return fmt.Sprintf("Op(%d)", int(op))
    85  	}
    86  
    87  	return opstr[op]
    88  }
    89  
    90  // An Args holds the instruction arguments.
    91  // If an instruction has fewer than 5 arguments,
    92  // the final elements in the array are nil.
    93  type Args [5]Arg
    94  
    95  // An Arg is a single instruction argument
    96  type Arg interface {
    97  	String() string
    98  }
    99  
   100  // A Reg is a single register.
   101  // The zero value denotes R0, not the absence of a register.
   102  type Reg uint16
   103  
   104  const (
   105  	// General-purpose register
   106  	R0 Reg = iota
   107  	R1
   108  	R2
   109  	R3
   110  	R4
   111  	R5
   112  	R6
   113  	R7
   114  	R8
   115  	R9
   116  	R10
   117  	R11
   118  	R12
   119  	R13
   120  	R14
   121  	R15
   122  	R16
   123  	R17
   124  	R18
   125  	R19
   126  	R20
   127  	R21
   128  	R22
   129  	R23
   130  	R24
   131  	R25
   132  	R26
   133  	R27
   134  	R28
   135  	R29
   136  	R30
   137  	R31
   138  
   139  	// Float point register
   140  	F0
   141  	F1
   142  	F2
   143  	F3
   144  	F4
   145  	F5
   146  	F6
   147  	F7
   148  	F8
   149  	F9
   150  	F10
   151  	F11
   152  	F12
   153  	F13
   154  	F14
   155  	F15
   156  	F16
   157  	F17
   158  	F18
   159  	F19
   160  	F20
   161  	F21
   162  	F22
   163  	F23
   164  	F24
   165  	F25
   166  	F26
   167  	F27
   168  	F28
   169  	F29
   170  	F30
   171  	F31
   172  )
   173  
   174  func (r Reg) String() string {
   175  	switch {
   176  	case r == R0:
   177  		return "$zero"
   178  
   179  	case r == R1:
   180  		return "$ra"
   181  
   182  	case r == R2:
   183  		return "$tp"
   184  
   185  	case r == R3:
   186  		return "$sp"
   187  
   188  	case (r >= R4) && (r <= R11):
   189  		return fmt.Sprintf("$a%d", int(r-R4))
   190  
   191  	case (r >= R12) && (r <= R20):
   192  		return fmt.Sprintf("$t%d", int(r-R12))
   193  
   194  	case r == R21:
   195  		return "$r21"
   196  
   197  	case r == R22:
   198  		return "$fp"
   199  
   200  	case (r >= R23) && (r <= R31):
   201  		return fmt.Sprintf("$s%d", int(r-R23))
   202  
   203  	case (r >= F0) && (r <= F7):
   204  		return fmt.Sprintf("$fa%d", int(r-F0))
   205  
   206  	case (r >= F8) && (r <= F23):
   207  		return fmt.Sprintf("$ft%d", int(r-F8))
   208  
   209  	case (r >= F24) && (r <= F31):
   210  		return fmt.Sprintf("$fs%d", int(r-F24))
   211  
   212  	default:
   213  		return fmt.Sprintf("Unknown(%d)", int(r))
   214  	}
   215  }
   216  
   217  // float control status register
   218  type Fcsr uint8
   219  
   220  const (
   221  	FCSR0 Fcsr = iota
   222  	FCSR1
   223  	FCSR2
   224  	FCSR3
   225  )
   226  
   227  func (f Fcsr) String() string {
   228  	return fmt.Sprintf("$fcsr%d", uint8(f))
   229  }
   230  
   231  // float condition flags register
   232  type Fcc uint8
   233  
   234  const (
   235  	FCC0 Fcc = iota
   236  	FCC1
   237  	FCC2
   238  	FCC3
   239  	FCC4
   240  	FCC5
   241  	FCC6
   242  	FCC7
   243  )
   244  
   245  func (f Fcc) String() string {
   246  	return fmt.Sprintf("$fcc%d", uint8(f))
   247  }
   248  
   249  // An Imm is an integer constant.
   250  type Uimm struct {
   251  	Imm     uint32
   252  	Decimal bool
   253  }
   254  
   255  func (i Uimm) String() string {
   256  	if i.Decimal == true {
   257  		return fmt.Sprintf("%d", i.Imm)
   258  	} else {
   259  		return fmt.Sprintf("%#x", i.Imm)
   260  	}
   261  }
   262  
   263  type Simm16 struct {
   264  	Imm   int16
   265  	Width uint8
   266  }
   267  
   268  func (si Simm16) String() string {
   269  	return fmt.Sprintf("%d", int32(si.Imm))
   270  }
   271  
   272  type Simm32 struct {
   273  	Imm   int32
   274  	Width uint8
   275  }
   276  
   277  func (si Simm32) String() string {
   278  	return fmt.Sprintf("%d", int32(si.Imm))
   279  }
   280  
   281  type OffsetSimm struct {
   282  	Imm   int32
   283  	Width uint8
   284  }
   285  
   286  func (o OffsetSimm) String() string {
   287  	return fmt.Sprintf("%d", int32(o.Imm))
   288  }
   289  
   290  type SaSimm int16
   291  
   292  func (s SaSimm) String() string {
   293  	return fmt.Sprintf("%#x", int(s))
   294  }
   295  
   296  type CodeSimm int16
   297  
   298  func (c CodeSimm) String() string {
   299  	return fmt.Sprintf("%#x", int(c))
   300  }
   301  

View as plain text