Source file src/cmd/vendor/golang.org/x/arch/arm/armasm/gnu.go

     1  // Copyright 2014 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 armasm
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"strings"
    11  )
    12  
    13  var saveDot = strings.NewReplacer(
    14  	".F16", "_dot_F16",
    15  	".F32", "_dot_F32",
    16  	".F64", "_dot_F64",
    17  	".S32", "_dot_S32",
    18  	".U32", "_dot_U32",
    19  	".FXS", "_dot_S",
    20  	".FXU", "_dot_U",
    21  	".32", "_dot_32",
    22  )
    23  
    24  // GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
    25  // This form typically matches the syntax defined in the ARM Reference Manual.
    26  func GNUSyntax(inst Inst) string {
    27  	var buf bytes.Buffer
    28  	op := inst.Op.String()
    29  	op = saveDot.Replace(op)
    30  	op = strings.Replace(op, ".", "", -1)
    31  	op = strings.Replace(op, "_dot_", ".", -1)
    32  	op = strings.ToLower(op)
    33  	buf.WriteString(op)
    34  	sep := " "
    35  	for i, arg := range inst.Args {
    36  		if arg == nil {
    37  			break
    38  		}
    39  		text := gnuArg(&inst, i, arg)
    40  		if text == "" {
    41  			continue
    42  		}
    43  		buf.WriteString(sep)
    44  		sep = ", "
    45  		buf.WriteString(text)
    46  	}
    47  	return buf.String()
    48  }
    49  
    50  func gnuArg(inst *Inst, argIndex int, arg Arg) string {
    51  	switch inst.Op &^ 15 {
    52  	case LDRD_EQ, LDREXD_EQ, STRD_EQ:
    53  		if argIndex == 1 {
    54  			// second argument in consecutive pair not printed
    55  			return ""
    56  		}
    57  	case STREXD_EQ:
    58  		if argIndex == 2 {
    59  			// second argument in consecutive pair not printed
    60  			return ""
    61  		}
    62  	}
    63  
    64  	switch arg := arg.(type) {
    65  	case Imm:
    66  		switch inst.Op &^ 15 {
    67  		case BKPT_EQ:
    68  			return fmt.Sprintf("%#04x", uint32(arg))
    69  		case SVC_EQ:
    70  			return fmt.Sprintf("%#08x", uint32(arg))
    71  		}
    72  		return fmt.Sprintf("#%d", int32(arg))
    73  
    74  	case ImmAlt:
    75  		return fmt.Sprintf("#%d, %d", arg.Val, arg.Rot)
    76  
    77  	case Mem:
    78  		R := gnuArg(inst, -1, arg.Base)
    79  		X := ""
    80  		if arg.Sign != 0 {
    81  			X = ""
    82  			if arg.Sign < 0 {
    83  				X = "-"
    84  			}
    85  			X += gnuArg(inst, -1, arg.Index)
    86  			if arg.Shift == ShiftLeft && arg.Count == 0 {
    87  				// nothing
    88  			} else if arg.Shift == RotateRightExt {
    89  				X += ", rrx"
    90  			} else {
    91  				X += fmt.Sprintf(", %s #%d", strings.ToLower(arg.Shift.String()), arg.Count)
    92  			}
    93  		} else {
    94  			X = fmt.Sprintf("#%d", arg.Offset)
    95  		}
    96  
    97  		switch arg.Mode {
    98  		case AddrOffset:
    99  			if X == "#0" {
   100  				return fmt.Sprintf("[%s]", R)
   101  			}
   102  			return fmt.Sprintf("[%s, %s]", R, X)
   103  		case AddrPreIndex:
   104  			return fmt.Sprintf("[%s, %s]!", R, X)
   105  		case AddrPostIndex:
   106  			return fmt.Sprintf("[%s], %s", R, X)
   107  		case AddrLDM:
   108  			if X == "#0" {
   109  				return R
   110  			}
   111  		case AddrLDM_WB:
   112  			if X == "#0" {
   113  				return R + "!"
   114  			}
   115  		}
   116  		return fmt.Sprintf("[%s Mode(%d) %s]", R, int(arg.Mode), X)
   117  
   118  	case PCRel:
   119  		return fmt.Sprintf(".%+#x", int32(arg)+4)
   120  
   121  	case Reg:
   122  		switch inst.Op &^ 15 {
   123  		case LDREX_EQ:
   124  			if argIndex == 0 {
   125  				return fmt.Sprintf("r%d", int32(arg))
   126  			}
   127  		}
   128  		switch arg {
   129  		case R10:
   130  			return "sl"
   131  		case R11:
   132  			return "fp"
   133  		case R12:
   134  			return "ip"
   135  		}
   136  
   137  	case RegList:
   138  		var buf bytes.Buffer
   139  		fmt.Fprintf(&buf, "{")
   140  		sep := ""
   141  		for i := 0; i < 16; i++ {
   142  			if arg&(1<<uint(i)) != 0 {
   143  				fmt.Fprintf(&buf, "%s%s", sep, gnuArg(inst, -1, Reg(i)))
   144  				sep = ", "
   145  			}
   146  		}
   147  		fmt.Fprintf(&buf, "}")
   148  		return buf.String()
   149  
   150  	case RegShift:
   151  		if arg.Shift == ShiftLeft && arg.Count == 0 {
   152  			return gnuArg(inst, -1, arg.Reg)
   153  		}
   154  		if arg.Shift == RotateRightExt {
   155  			return gnuArg(inst, -1, arg.Reg) + ", rrx"
   156  		}
   157  		return fmt.Sprintf("%s, %s #%d", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), arg.Count)
   158  
   159  	case RegShiftReg:
   160  		return fmt.Sprintf("%s, %s %s", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), gnuArg(inst, -1, arg.RegCount))
   161  
   162  	}
   163  	return strings.ToLower(arg.String())
   164  }
   165  

View as plain text