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 == ANDI && inst.Args[2].(Simm).Imm == 255 {
    46  			op = "zext.b"
    47  			args = args[:len(args)-1]
    48  		}
    49  
    50  		if inst.Op == ADDIW && inst.Args[2].(Simm).Imm == 0 {
    51  			op = "sext.w"
    52  			args = args[:len(args)-1]
    53  		}
    54  
    55  		if inst.Op == XORI && inst.Args[2].(Simm).String() == "-1" {
    56  			op = "not"
    57  			args = args[:len(args)-1]
    58  		}
    59  
    60  	case ADD:
    61  		if inst.Args[1].(Reg) == X0 {
    62  			op = "mv"
    63  			args[1] = args[2]
    64  			args = args[:len(args)-1]
    65  		}
    66  
    67  	case BEQ:
    68  		if inst.Args[1].(Reg) == X0 {
    69  			op = "beqz"
    70  			args[1] = args[2]
    71  			args = args[:len(args)-1]
    72  		}
    73  
    74  	case BGE:
    75  		if inst.Args[1].(Reg) == X0 {
    76  			op = "bgez"
    77  			args[1] = args[2]
    78  			args = args[:len(args)-1]
    79  		} else if inst.Args[0].(Reg) == X0 {
    80  			op = "blez"
    81  			args[0], args[1] = args[1], args[2]
    82  			args = args[:len(args)-1]
    83  		}
    84  
    85  	case BLT:
    86  		if inst.Args[1].(Reg) == X0 {
    87  			op = "bltz"
    88  			args[1] = args[2]
    89  			args = args[:len(args)-1]
    90  		} else if inst.Args[0].(Reg) == X0 {
    91  			op = "bgtz"
    92  			args[0], args[1] = args[1], args[2]
    93  			args = args[:len(args)-1]
    94  		}
    95  
    96  	case BNE:
    97  		if inst.Args[1].(Reg) == X0 {
    98  			op = "bnez"
    99  			args[1] = args[2]
   100  			args = args[:len(args)-1]
   101  		}
   102  
   103  	case CSRRC:
   104  		if inst.Args[0].(Reg) == X0 {
   105  			op = "csrc"
   106  			args[0], args[1] = args[1], args[2]
   107  			args = args[:len(args)-1]
   108  		}
   109  
   110  	case CSRRCI:
   111  		if inst.Args[0].(Reg) == X0 {
   112  			op = "csrci"
   113  			args[0], args[1] = args[1], args[2]
   114  			args = args[:len(args)-1]
   115  		}
   116  
   117  	case CSRRS:
   118  		if inst.Args[2].(Reg) == X0 {
   119  			switch inst.Args[1].(CSR) {
   120  			case FCSR:
   121  				op = "frcsr"
   122  				args = args[:len(args)-2]
   123  
   124  			case FFLAGS:
   125  				op = "frflags"
   126  				args = args[:len(args)-2]
   127  
   128  			case FRM:
   129  				op = "frrm"
   130  				args = args[:len(args)-2]
   131  
   132  			// rdcycleh, rdinstreth and rdtimeh are RV-32 only instructions.
   133  			// So not included there.
   134  			case CYCLE:
   135  				op = "rdcycle"
   136  				args = args[:len(args)-2]
   137  
   138  			case INSTRET:
   139  				op = "rdinstret"
   140  				args = args[:len(args)-2]
   141  
   142  			case TIME:
   143  				op = "rdtime"
   144  				args = args[:len(args)-2]
   145  
   146  			default:
   147  				op = "csrr"
   148  				args = args[:len(args)-1]
   149  			}
   150  		} else if inst.Args[0].(Reg) == X0 {
   151  			op = "csrs"
   152  			args[0], args[1] = args[1], args[2]
   153  			args = args[:len(args)-1]
   154  		}
   155  
   156  	case CSRRSI:
   157  		if inst.Args[0].(Reg) == X0 {
   158  			op = "csrsi"
   159  			args[0], args[1] = args[1], args[2]
   160  			args = args[:len(args)-1]
   161  		}
   162  
   163  	case CSRRW:
   164  		switch inst.Args[1].(CSR) {
   165  		case FCSR:
   166  			op = "fscsr"
   167  			if inst.Args[0].(Reg) == X0 {
   168  				args[0] = args[2]
   169  				args = args[:len(args)-2]
   170  			} else {
   171  				args[1] = args[2]
   172  				args = args[:len(args)-1]
   173  			}
   174  
   175  		case FFLAGS:
   176  			op = "fsflags"
   177  			if inst.Args[0].(Reg) == X0 {
   178  				args[0] = args[2]
   179  				args = args[:len(args)-2]
   180  			} else {
   181  				args[1] = args[2]
   182  				args = args[:len(args)-1]
   183  			}
   184  
   185  		case FRM:
   186  			op = "fsrm"
   187  			if inst.Args[0].(Reg) == X0 {
   188  				args[0] = args[2]
   189  				args = args[:len(args)-2]
   190  			} else {
   191  				args[1] = args[2]
   192  				args = args[:len(args)-1]
   193  			}
   194  
   195  		case CYCLE:
   196  			if inst.Args[0].(Reg) == X0 && inst.Args[2].(Reg) == X0 {
   197  				op = "unimp"
   198  				args = nil
   199  			}
   200  
   201  		default:
   202  			if inst.Args[0].(Reg) == X0 {
   203  				op = "csrw"
   204  				args[0], args[1] = args[1], args[2]
   205  				args = args[:len(args)-1]
   206  			}
   207  		}
   208  
   209  	case CSRRWI:
   210  		if inst.Args[0].(Reg) == X0 {
   211  			op = "csrwi"
   212  			args[0], args[1] = args[1], args[2]
   213  			args = args[:len(args)-1]
   214  		}
   215  
   216  	// When both pred and succ equals to iorw, the GNU objdump will omit them.
   217  	case FENCE:
   218  		if inst.Args[0].(MemOrder).String() == "iorw" &&
   219  			inst.Args[1].(MemOrder).String() == "iorw" {
   220  			args = nil
   221  		}
   222  
   223  	case FSGNJX_D:
   224  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   225  			op = "fabs.d"
   226  			args = args[:len(args)-1]
   227  		}
   228  
   229  	case FSGNJX_S:
   230  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   231  			op = "fabs.s"
   232  			args = args[:len(args)-1]
   233  		}
   234  
   235  	case FSGNJ_D:
   236  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   237  			op = "fmv.d"
   238  			args = args[:len(args)-1]
   239  		}
   240  
   241  	case FSGNJ_S:
   242  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   243  			op = "fmv.s"
   244  			args = args[:len(args)-1]
   245  		}
   246  
   247  	case FSGNJN_D:
   248  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   249  			op = "fneg.d"
   250  			args = args[:len(args)-1]
   251  		}
   252  
   253  	case FSGNJN_S:
   254  		if inst.Args[1].(Reg) == inst.Args[2].(Reg) {
   255  			op = "fneg.s"
   256  			args = args[:len(args)-1]
   257  		}
   258  
   259  	case JAL:
   260  		if inst.Args[0].(Reg) == X0 {
   261  			op = "j"
   262  			args[0] = args[1]
   263  			args = args[:len(args)-1]
   264  		} else if inst.Args[0].(Reg) == X1 {
   265  			op = "jal"
   266  			args[0] = args[1]
   267  			args = args[:len(args)-1]
   268  		}
   269  
   270  	case JALR:
   271  		if inst.Args[0].(Reg) == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
   272  			args[0] = inst.Args[1].(RegOffset).OfsReg.String()
   273  			args = args[:len(args)-1]
   274  		}
   275  
   276  		if inst.Args[0].(Reg) == X0 {
   277  			if inst.Args[1].(RegOffset).OfsReg == X1 && inst.Args[1].(RegOffset).Ofs.Imm == 0 {
   278  				op = "ret"
   279  				args = nil
   280  			} else if inst.Args[1].(RegOffset).Ofs.Imm == 0 {
   281  				op = "jr"
   282  				args[0] = inst.Args[1].(RegOffset).OfsReg.String()
   283  				args = args[:len(args)-1]
   284  			} else {
   285  				op = "jr"
   286  				args[0] = inst.Args[1].(RegOffset).String()
   287  				args = args[:len(args)-1]
   288  			}
   289  		}
   290  
   291  	case SLTIU:
   292  		if inst.Args[2].(Simm).String() == "1" {
   293  			op = "seqz"
   294  			args = args[:len(args)-1]
   295  		}
   296  
   297  	case SLT:
   298  		if inst.Args[1].(Reg) == X0 {
   299  			op = "sgtz"
   300  			args[1] = args[2]
   301  			args = args[:len(args)-1]
   302  		} else if inst.Args[2].(Reg) == X0 {
   303  			op = "sltz"
   304  			args = args[:len(args)-1]
   305  		}
   306  
   307  	case SLTU:
   308  		if inst.Args[1].(Reg) == X0 {
   309  			op = "snez"
   310  			args[1] = args[2]
   311  			args = args[:len(args)-1]
   312  		}
   313  
   314  	case SUB:
   315  		if inst.Args[1].(Reg) == X0 {
   316  			op = "neg"
   317  			args[1] = args[2]
   318  			args = args[:len(args)-1]
   319  		}
   320  
   321  	case SUBW:
   322  		if inst.Args[1].(Reg) == X0 {
   323  			op = "negw"
   324  			args[1] = args[2]
   325  			args = args[:len(args)-1]
   326  		}
   327  	}
   328  
   329  	if args != nil {
   330  		op += " " + strings.Join(args, ",")
   331  	}
   332  	return op
   333  }
   334  

View as plain text