github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/internal/asm/arch/arm.go (about)

     1  // Copyright 2015 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.assembler file.
     4  
     5  // This file encapsulates some of the odd characteristics of the ARM
     6  // instruction set, to minimize its interaction with the core of the
     7  // assembler.
     8  
     9  package arch
    10  
    11  import (
    12  	"strings"
    13  
    14  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/obj"
    15  	"github.com/Rookout/GoSDK/pkg/services/assembler/internal/obj/arm"
    16  )
    17  
    18  var armLS = map[string]uint8{
    19  	"U":  arm.C_UBIT,
    20  	"S":  arm.C_SBIT,
    21  	"W":  arm.C_WBIT,
    22  	"P":  arm.C_PBIT,
    23  	"PW": arm.C_WBIT | arm.C_PBIT,
    24  	"WP": arm.C_WBIT | arm.C_PBIT,
    25  }
    26  
    27  var armSCOND = map[string]uint8{
    28  	"EQ":  arm.C_SCOND_EQ,
    29  	"NE":  arm.C_SCOND_NE,
    30  	"CS":  arm.C_SCOND_HS,
    31  	"HS":  arm.C_SCOND_HS,
    32  	"CC":  arm.C_SCOND_LO,
    33  	"LO":  arm.C_SCOND_LO,
    34  	"MI":  arm.C_SCOND_MI,
    35  	"PL":  arm.C_SCOND_PL,
    36  	"VS":  arm.C_SCOND_VS,
    37  	"VC":  arm.C_SCOND_VC,
    38  	"HI":  arm.C_SCOND_HI,
    39  	"LS":  arm.C_SCOND_LS,
    40  	"GE":  arm.C_SCOND_GE,
    41  	"LT":  arm.C_SCOND_LT,
    42  	"GT":  arm.C_SCOND_GT,
    43  	"LE":  arm.C_SCOND_LE,
    44  	"AL":  arm.C_SCOND_NONE,
    45  	"U":   arm.C_UBIT,
    46  	"S":   arm.C_SBIT,
    47  	"W":   arm.C_WBIT,
    48  	"P":   arm.C_PBIT,
    49  	"PW":  arm.C_WBIT | arm.C_PBIT,
    50  	"WP":  arm.C_WBIT | arm.C_PBIT,
    51  	"F":   arm.C_FBIT,
    52  	"IBW": arm.C_WBIT | arm.C_PBIT | arm.C_UBIT,
    53  	"IAW": arm.C_WBIT | arm.C_UBIT,
    54  	"DBW": arm.C_WBIT | arm.C_PBIT,
    55  	"DAW": arm.C_WBIT,
    56  	"IB":  arm.C_PBIT | arm.C_UBIT,
    57  	"IA":  arm.C_UBIT,
    58  	"DB":  arm.C_PBIT,
    59  	"DA":  0,
    60  }
    61  
    62  var armJump = map[string]bool{
    63  	"B":    true,
    64  	"BL":   true,
    65  	"BX":   true,
    66  	"BEQ":  true,
    67  	"BNE":  true,
    68  	"BCS":  true,
    69  	"BHS":  true,
    70  	"BCC":  true,
    71  	"BLO":  true,
    72  	"BMI":  true,
    73  	"BPL":  true,
    74  	"BVS":  true,
    75  	"BVC":  true,
    76  	"BHI":  true,
    77  	"BLS":  true,
    78  	"BGE":  true,
    79  	"BLT":  true,
    80  	"BGT":  true,
    81  	"BLE":  true,
    82  	"CALL": true,
    83  	"JMP":  true,
    84  }
    85  
    86  func jumpArm(word string) bool {
    87  	return armJump[word]
    88  }
    89  
    90  
    91  
    92  func IsARMCMP(op obj.As) bool {
    93  	switch op {
    94  	case arm.ACMN, arm.ACMP, arm.ATEQ, arm.ATST:
    95  		return true
    96  	}
    97  	return false
    98  }
    99  
   100  
   101  
   102  func IsARMSTREX(op obj.As) bool {
   103  	switch op {
   104  	case arm.ASTREX, arm.ASTREXD, arm.ASWPW, arm.ASWPBU:
   105  		return true
   106  	}
   107  	return false
   108  }
   109  
   110  
   111  
   112  
   113  const aMCR = arm.ALAST + 1
   114  
   115  
   116  
   117  func IsARMMRC(op obj.As) bool {
   118  	switch op {
   119  	case arm.AMRC, aMCR: 
   120  		return true
   121  	}
   122  	return false
   123  }
   124  
   125  
   126  
   127  func IsARMBFX(op obj.As) bool {
   128  	switch op {
   129  	case arm.ABFX, arm.ABFXU, arm.ABFC, arm.ABFI:
   130  		return true
   131  	}
   132  	return false
   133  }
   134  
   135  
   136  func IsARMFloatCmp(op obj.As) bool {
   137  	switch op {
   138  	case arm.ACMPF, arm.ACMPD:
   139  		return true
   140  	}
   141  	return false
   142  }
   143  
   144  
   145  
   146  
   147  
   148  func ARMMRCOffset(op obj.As, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int64, op0 obj.As, ok bool) {
   149  	op1 := int64(0)
   150  	if op == arm.AMRC {
   151  		op1 = 1
   152  	}
   153  	bits, ok := ParseARMCondition(cond)
   154  	if !ok {
   155  		return
   156  	}
   157  	offset = (0xe << 24) | 
   158  		(op1 << 20) | 
   159  		((int64(bits) ^ arm.C_SCOND_XOR) << 28) | 
   160  		((x0 & 15) << 8) | 
   161  		((x1 & 7) << 21) | 
   162  		((x2 & 15) << 12) | 
   163  		((x3 & 15) << 16) | 
   164  		((x4 & 15) << 0) | 
   165  		((x5 & 7) << 5) | 
   166  		(1 << 4) 
   167  	return offset, arm.AMRC, true
   168  }
   169  
   170  
   171  
   172  func IsARMMULA(op obj.As) bool {
   173  	switch op {
   174  	case arm.AMULA, arm.AMULS, arm.AMMULA, arm.AMMULS, arm.AMULABB, arm.AMULAWB, arm.AMULAWT:
   175  		return true
   176  	}
   177  	return false
   178  }
   179  
   180  var bcode = []obj.As{
   181  	arm.ABEQ,
   182  	arm.ABNE,
   183  	arm.ABCS,
   184  	arm.ABCC,
   185  	arm.ABMI,
   186  	arm.ABPL,
   187  	arm.ABVS,
   188  	arm.ABVC,
   189  	arm.ABHI,
   190  	arm.ABLS,
   191  	arm.ABGE,
   192  	arm.ABLT,
   193  	arm.ABGT,
   194  	arm.ABLE,
   195  	arm.AB,
   196  	obj.ANOP,
   197  }
   198  
   199  
   200  
   201  func ARMConditionCodes(prog *obj.Prog, cond string) bool {
   202  	if cond == "" {
   203  		return true
   204  	}
   205  	bits, ok := ParseARMCondition(cond)
   206  	if !ok {
   207  		return false
   208  	}
   209  	
   210  	if prog.As == arm.AB {
   211  		prog.As = bcode[(bits^arm.C_SCOND_XOR)&0xf]
   212  		bits = (bits &^ 0xf) | arm.C_SCOND_NONE
   213  	}
   214  	prog.Scond = bits
   215  	return true
   216  }
   217  
   218  
   219  
   220  
   221  func ParseARMCondition(cond string) (uint8, bool) {
   222  	return parseARMCondition(cond, armLS, armSCOND)
   223  }
   224  
   225  func parseARMCondition(cond string, ls, scond map[string]uint8) (uint8, bool) {
   226  	cond = strings.TrimPrefix(cond, ".")
   227  	if cond == "" {
   228  		return arm.C_SCOND_NONE, true
   229  	}
   230  	names := strings.Split(cond, ".")
   231  	bits := uint8(0)
   232  	for _, name := range names {
   233  		if b, present := ls[name]; present {
   234  			bits |= b
   235  			continue
   236  		}
   237  		if b, present := scond[name]; present {
   238  			bits = (bits &^ arm.C_SCOND) | b
   239  			continue
   240  		}
   241  		return 0, false
   242  	}
   243  	return bits, true
   244  }
   245  
   246  func armRegisterNumber(name string, n int16) (int16, bool) {
   247  	if n < 0 || 15 < n {
   248  		return 0, false
   249  	}
   250  	switch name {
   251  	case "R":
   252  		return arm.REG_R0 + n, true
   253  	case "F":
   254  		return arm.REG_F0 + n, true
   255  	}
   256  	return 0, false
   257  }