1// Copyright (c) 2014, Google Inc.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15// This package generates chacha_vec_arm.S from chacha_vec.c. Install the
16// arm-linux-gnueabihf-gcc compiler as described in BUILDING.md. Then:
17// `(cd crypto/chacha && go run chacha_vec_arm_generate.go)`.
18
19package main
20
21import (
22	"bufio"
23	"bytes"
24	"os"
25	"os/exec"
26	"strings"
27)
28
29const defaultCompiler = "/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"
30
31func main() {
32	compiler := defaultCompiler
33	if len(os.Args) > 1 {
34		compiler = os.Args[1]
35	}
36
37	args := []string{
38		"-O3",
39		"-mcpu=cortex-a8",
40		"-mfpu=neon",
41		"-fpic",
42		"-DASM_GEN",
43		"-I", "../../include",
44		"-S", "chacha_vec.c",
45		"-o", "-",
46	}
47
48	output, err := os.OpenFile("chacha_vec_arm.S", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
49	if err != nil {
50		panic(err)
51	}
52	defer output.Close()
53
54	output.WriteString(preamble)
55	output.WriteString(compiler)
56	output.WriteString(" ")
57	output.WriteString(strings.Join(args, " "))
58	output.WriteString("\n\n#if !defined(OPENSSL_NO_ASM)\n")
59	output.WriteString("#if defined(__arm__)\n\n")
60
61	cmd := exec.Command(compiler, args...)
62	cmd.Stderr = os.Stderr
63	asm, err := cmd.StdoutPipe()
64	if err != nil {
65		panic(err)
66	}
67	if err := cmd.Start(); err != nil {
68		panic(err)
69	}
70
71	attr28 := []byte(".eabi_attribute 28,")
72	globalDirective := []byte(".global\t")
73	newLine := []byte("\n")
74	attr28Handled := false
75
76	scanner := bufio.NewScanner(asm)
77	for scanner.Scan() {
78		line := scanner.Bytes()
79
80		if bytes.Contains(line, attr28) {
81			output.WriteString(attr28Block)
82			attr28Handled = true
83			continue
84		}
85
86		output.Write(line)
87		output.Write(newLine)
88
89		if i := bytes.Index(line, globalDirective); i >= 0 {
90			output.Write(line[:i])
91			output.WriteString(".hidden\t")
92			output.Write(line[i+len(globalDirective):])
93			output.Write(newLine)
94		}
95	}
96
97	if err := scanner.Err(); err != nil {
98		panic(err)
99	}
100
101	if !attr28Handled {
102		panic("EABI attribute 28 not seen in processing")
103	}
104
105	if err := cmd.Wait(); err != nil {
106		panic(err)
107	}
108
109	output.WriteString(trailer)
110}
111
112const preamble = `# Copyright (c) 2014, Google Inc.
113#
114# Permission to use, copy, modify, and/or distribute this software for any
115# purpose with or without fee is hereby granted, provided that the above
116# copyright notice and this permission notice appear in all copies.
117#
118# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
119# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
120# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
121# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
122# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
123# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
124# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
125
126# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
127# needed to support switching on NEON code at runtime. If the whole of OpenSSL
128# were to be compiled with the needed flags to build chacha_vec.c, then it
129# wouldn't be possible to run on non-NEON systems.
130#
131# This file was generated by chacha_vec_arm_generate.go using the following
132# compiler command:
133#
134#     `
135
136const attr28Block = `
137# EABI attribute 28 sets whether VFP register arguments were used to build this
138# file. If object files are inconsistent on this point, the linker will refuse
139# to link them. Thus we report whatever the compiler expects since we don't use
140# VFP arguments.
141
142#if defined(__ARM_PCS_VFP)
143	.eabi_attribute 28, 1
144#else
145	.eabi_attribute 28, 0
146#endif
147
148`
149
150const trailer = `
151#endif  /* __arm__ */
152#endif  /* !OPENSSL_NO_ASM */
153`
154