Source file src/cmd/vendor/golang.org/x/arch/riscv64/riscv64asm/gnu.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 riscv64asm
     6  
     7  import (
     8  	"strings"
     9  )
    10  
    11  // GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
    12  // This form typically matches the syntax defined in the RISC-V Instruction Set Manual. See
    13  // https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf
    14  func GNUSyntax(inst Inst) string {
    15  	op := strings.ToLower(inst.Op.String())
    16  	var args []string
    17  	for _, a := range inst.Args {
    18  		if a == nil {
    19  			break
    20  		}
    21  		args = append(args, strings.ToLower(a.String()))
    22  	}
    23  
    24  	switch inst.Op {
    25  	case ADDI, ADDIW, ANDI, ORI, SLLI, SLLIW, SRAI, SRAIW, SRLI, SRLIW, XORI:
    26  		if inst.Op == ADDI {
    27  			if inst.Args[1].(Reg) == X0 && inst.Args[0].(Reg) != X0 {
    28  				op = "li"
    29  				args[1] = args[2]
    30  				args = args[:len(args)-1]
    31  				break
    32  			}
    33  
    34  			if inst.Args[2].(Simm).Imm == 0 {
    35  				if inst.Args[0].(Reg) == X0 && inst.Args[1].(Reg) == X0 {
    36  					op = "nop"
    37  					args = nil
    38  				} else {
    39  					op = "mv"
    40  					args = args[:len(args)-1]
    41  				}
    42  			}
    43  		}
    44  
    45  		if inst.Op == ADDIW && inst.Args[2].(Simm).Imm == 0 {
    46  			op = "sext.w"
    47  			args = args[:len(args)-1]
    48  		}
    49  
    50  		if inst.Op == XORI && inst.Args[2].(Simm).String() == "-1" {
    51  			op = "not"
    52  			args = args[:len(args)-1]
    53  		}
    54  
    55  	case ADD:
    56  		if inst.Args[1].(Reg) == X0 {
    57  			op = "mv"
    58  			args[1] = args[2]
    59  			args = args[:len(args)-1]
    60  		}
    61  
    62  	case BEQ:
    63  		if inst.Args[1].(Reg) == X0 {
    64  			op = "beqz"
    65  			args[1] = args[2]
    66  			args = args[:len(args)-1]
    67  		}
    68  
    69  	case BGE:
    70  		if inst.Args[1].(Reg) == X0 {
    71  			op = "bgez"
    72  			args[1] = args[2]
    73  			args = args[:len(args)-1]
    74  		} else if inst.Args[0].(Reg) == X0 {
    75  			op = "blez"
    76  			args[0], args[1] = args[1], args[2]
    77  			args = args[:len(args)-1]
    78  		}
    79  
    80  	case BLT:
    81  		if inst.Args[1].(Reg) == X0 {
    82  			op = "bltz"
    83  			args[1] = args[2]
    84  			args = args[:len(args)-1]
    85  		} else if inst.Args[0].(Reg) == X0 {
    86  			op = "bgtz"
    87  			args[0], args[1] = args[1], args[2]
    88  			args = args[:len(args)-1]
    89  		}
    90  
    91  	case BNE:
    92  		if inst.Args[1].(Reg) == X0 {
    93  			op = "bnez"
    94  			args[1] = args[2]
    95  			args = args[:len(args)-1]
    96  		}
    97  
    98  	case CSRRC:
    99  		if inst.Args[0].(Reg) == X0 {
   100  			op = "csrc"
   101  			args[0], args[1] = args[1], args[2]
   102  			args = args[:len(args)-1]
   103  		}
   104  
   105  	case CSRRCI:
   106  		if inst.Args[0].(Reg) == X0 {
   107  			op = "csrci"
   108  			args[0], args[1] = args[1], args[2]
   109  			args = args[:len(args)-1]
   110  		}
   111  
   112  	case CSRRS:
   113  		if inst.Args[2].(Reg) == X0 {
   114  			switch inst.Args[1].(CSR) {
   115  			case FCSR:
   116  				op = "frcsr"
   117  				args = args[:len(args)-2]
   118  
   119  			case FFLAGS:
   120  				op = "frflags"
   121  				args = args[:len(args)-2]
   122  
   123  			case FRM:
   124  				op = "frrm"
   125  				args = args[:len(args)-2]
   126  
   127  			// rdcycleh, rdinstreth and rdtimeh are RV-32 only instructions.
   128  			// So not included there.
   129  			case CYCLE:
   130  				op = "rdcycle"
   131  				args = args[:len(args)-2]
   132  
   133  			case INSTRET:
   134  				op = "rdinstret"
   135  				args = args[:len(args)-2]
   136  
   137  			case TIME:
   138  				op = "rdtime"
   139  				args = args[:len(args)-2]
   140  
   141  			default:
   142  				op = "csrr"
   143  				args = args[:len(args)-1]
   144  			}
   145  		} else if inst.Args[0].(Reg) == X0 {
   146  			op = "csrs"
   147  			args[0], args[1] = args[1], args[2]
   148  			args = args[:len(args)-1]
   149  		}
   150  
   151  	case CSRRSI:
   152  		if inst.Args[0].(Reg) == X0 {
   153  			op = "csrsi"
   154  			args[0], args[1] = args[1], args[2]
   155  			args = args[:len(args)-1]
   156  		}
   157  
   158  	case CSRRW:
   159  		switch inst.Args[1].(CSR) {
   160  		case FCSR:
   161  			op = "fscsr"
   162  			if inst.Args[0].(Reg) == X0 {
   163  				args[0] = args[2]
   164  				args = args[:len(args)-2]
   165  			} else {
   166  				args[1] = args[2]
   167  				args = args[:len(args)-1]
   168  			}
   169  
   170  		case FFLAGS:
   171  			op = "fsflags"
   172  			if inst.Args[0].(Reg) == X0 {
   173  				args[0] = args[2]
   174  				args = args[:len(args)-2]
   175  			} else {
   176  				args[1] = args[2]
   177  				args = args[:len(args)-1]
   178  			}
   179  
   180  		case FRM:
   181  			op = "fsrm"
   182  			if inst.Args[0].(Reg) == X0 {
   183  				args[0] = args[2]
   184  				args = args[:len(args)-2]
   185  			} else {
   186  				args[1] = args[2]
   187  				args = args[:len(args)-1]
   188  			}
   189  
   190  		case CYCLE:
   191  			if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 {
   192  				op = "unimp"
   193  				args = nil
   194  			}
   195  
   196  		default:
   197  			if inst.Args[0].(Reg) == X0 {
   198  				op = "csrw"
   199  				args[0], args[1] = args[1], args[2]
   200  				args = args[:len(args)-1]
   201  			}
   202  		}
   203  
   204  	case CSRRWI:
   205  		if inst.Args[0].(Reg) == X0 {
   206  			op = "csrwi"
   207  			args[0], args[1] = args[1], args[2]
   208  			args = args[:len(args)-1]
   209  		}
   210  
   211  	// When both pred and succ equals to iorw, the GNU objdump will omit them.
   212  	case FENCE:
   213  		if inst.Args[0].(MemOrder).String() == "iorw" &&
   214  			inst.Args[1].(MemOrder).String() == "iorw" {
   215  			args = nil
   216  		}
   217  
   218  	case FSGNJX_D:
   219  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   220  			op = "fabs.d"
   221  			args = args[:len(args)-1]
   222  		}
   223  
   224  	case FSGNJX_S:
   225  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   226  			op = "fabs.s"
   227  			args = args[:len(args)-1]
   228  		}
   229  
   230  	case FSGNJ_D:
   231  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   232  			op = "fmv.d"
   233  			args = args[:len(args)-1]
   234  		}
   235  
   236  	case FSGNJ_S:
   237  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   238  			op = "fmv.s"
   239  			args = args[:len(args)-1]
   240  		}
   241  
   242  	case FSGNJN_D:
   243  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   244  			op = "fneg.d"
   245  			args = args[:len(args)-1]
   246  		}
   247  
   248  	case FSGNJN_S:
   249  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   250  			op = "fneg.s"
   251  			args = args[:len(args)-1]
   252  		}
   253  
   254  	case JAL:
   255  		if inst.Args[0].(Reg) == X0 {
   256  			op = "j"
   257  			args[0] = args[1]
   258  			args = args[:len(args)-1]
   259  		} else if inst.Args[0].(Reg) == X1 {
   260  			op = "jal"
   261  			args[0] = args[1]
   262  			args = args[:len(args)-1]
   263  		}
   264  
   265  	case JALR:
   266  		if inst.Args[0].(Reg) == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
   267  			args[0] = inst.Args[1].(RegOffset).OfsReg.String()
   268  			args = args[:len(args)-1]
   269  		}
   270  
   271  		if inst.Args[0].(Reg) == X0 {
   272  			if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
   273  				op = "ret"
   274  				args = nil
   275  			} else if inst.Args[1].(RegOffset).Ofs.Imm == 0 {
   276  				op = "jr"
   277  				args[0] = inst.Args[1].(RegOffset).OfsReg.String()
   278  				args = args[:len(args)-1]
   279  			} else {
   280  				op = "jr"
   281  				args[0] = inst.Args[1].(RegOffset).String()
   282  				args = args[:len(args)-1]
   283  			}
   284  		}
   285  
   286  	case SLTIU:
   287  		if inst.Args[2].(Simm).String() == "1" {
   288  			op = "seqz"
   289  			args = args[:len(args)-1]
   290  		}
   291  
   292  	case SLT:
   293  		if inst.Args[1].(Reg) == X0 {
   294  			op = "sgtz"
   295  			args[1] = args[2]
   296  			args = args[:len(args)-1]
   297  		} else if inst.Args[2].(Reg) == X0 {
   298  			op = "sltz"
   299  			args = args[:len(args)-1]
   300  		}
   301  
   302  	case SLTU:
   303  		if inst.Args[1].(Reg) == X0 {
   304  			op = "snez"
   305  			args[1] = args[2]
   306  			args = args[:len(args)-1]
   307  		}
   308  
   309  	case SUB:
   310  		if inst.Args[1].(Reg) == X0 {
   311  			op = "neg"
   312  			args[1] = args[2]
   313  			args = args[:len(args)-1]
   314  		}
   315  
   316  	case SUBW:
   317  		if inst.Args[1].(Reg) == X0 {
   318  			op = "negw"
   319  			args[1] = args[2]
   320  			args = args[:len(args)-1]
   321  		}
   322  	}
   323  
   324  	if args != nil {
   325  		op += " " + strings.Join(args, ",")
   326  	}
   327  	return op
   328  }
   329  

View as plain text