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 }