gitee.com/quant1x/num@v0.3.2/asm/asm2plan9/asm2plan9s_arm64.go (about)

     1  /*
     2   * Minio Cloud Storage, (C) 2016-2017 Minio, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package main
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  	"os/exec"
    25  	"regexp"
    26  	"strings"
    27  )
    28  
    29  func as(instructions []Instruction) error {
    30  
    31  	// First to yasm (will return error when not installed)
    32  	e := yasm(instructions)
    33  	if e == nil {
    34  		return e
    35  	}
    36  	// Try gas if yasm not installed
    37  	return gas(instructions)
    38  }
    39  
    40  func gas(instructions []Instruction) error {
    41  	for i, ins := range instructions {
    42  		assembled, opcodes, err := asSingle(ins.instruction, ins.lineno, ins.commentPos, ins.inDefine)
    43  		if err != nil {
    44  			return err
    45  		}
    46  		instructions[i].assembled = assembled
    47  		instructions[i].opcodes = make([]byte, len(opcodes))
    48  		copy(instructions[i].opcodes[:], opcodes)
    49  	}
    50  	return nil
    51  }
    52  
    53  func asSingle(instr string, lineno, commentPos int, inDefine bool) (string, []byte, error) {
    54  
    55  	instrFields := strings.Split(instr, "/*")
    56  	content := []byte(instrFields[0] + "\n")
    57  	tmpfile, err := ioutil.TempFile("", "asm2plan9s")
    58  	if err != nil {
    59  		return "", nil, err
    60  	}
    61  
    62  	if _, err := tmpfile.Write(content); err != nil {
    63  		return "", nil, err
    64  	}
    65  	if err := tmpfile.Close(); err != nil {
    66  		return "", nil, err
    67  	}
    68  
    69  	asmFile := tmpfile.Name() + ".asm"
    70  	lisFile := tmpfile.Name() + ".lis"
    71  	objFile := tmpfile.Name() + ".obj"
    72  	os.Rename(tmpfile.Name(), asmFile)
    73  
    74  	defer os.Remove(asmFile) // clean up
    75  	defer os.Remove(lisFile) // clean up
    76  	defer os.Remove(objFile) // clean up
    77  
    78  	// as -march=armv8-a+crypto -o first.out -al=first.lis first.s
    79  	app := "as"
    80  
    81  	arg0 := "-march=armv8-a+crypto" // See https://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/ARM-Options.html
    82  	arg1 := "-o"
    83  	arg2 := objFile
    84  	arg3 := fmt.Sprintf("-al=%s", lisFile)
    85  	arg4 := asmFile
    86  
    87  	cmd := exec.Command(app, arg0, arg1, arg2, arg3, arg4)
    88  	cmb, err := cmd.CombinedOutput()
    89  	if err != nil {
    90  		asmErrs := strings.Split(string(cmb)[len(asmFile)+1:], ":")
    91  		asmErr := strings.Join(asmErrs[1:], ":")
    92  		return "", nil, errors.New(fmt.Sprintf("GAS error (line %d for '%s'):", lineno+1, strings.TrimSpace(instr)) + asmErr)
    93  	}
    94  
    95  	return toPlan9sArm(lisFile, instr)
    96  }
    97  
    98  func toPlan9sArm(listFile, instr string) (string, []byte, error) {
    99  
   100  	var r = regexp.MustCompile(`^\s+\d+\s+\d+\s+([0-9a-fA-F]+)`)
   101  
   102  	outputLines, err := readLines(listFile, nil)
   103  	if err != nil {
   104  		return "", nil, err
   105  	}
   106  
   107  	lastLine := outputLines[len(outputLines)-1]
   108  
   109  	sline := "    "
   110  
   111  	if match := r.FindStringSubmatch(lastLine); len(match) > 1 {
   112  		sline += fmt.Sprintf("WORD $0x%s%s%s%s", strings.ToLower(match[1][6:8]), strings.ToLower(match[1][4:6]), strings.ToLower(match[1][2:4]), strings.ToLower(match[1][0:2]))
   113  	} else {
   114  		return "", nil, errors.New("regexp failed")
   115  	}
   116  
   117  	sline += " //" + instr
   118  
   119  	// fmt.Println(sline)
   120  
   121  	return sline, nil, nil
   122  }