mksys.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. package main
  10. import (
  11. "encoding/json"
  12. "flag"
  13. "fmt"
  14. "io/ioutil"
  15. "log"
  16. "os"
  17. "path"
  18. "strings"
  19. "text/template"
  20. )
  21. type Syscall struct {
  22. Ret []string
  23. Args []string
  24. Name string
  25. Id uint32
  26. Define string
  27. Sysname string
  28. Libname string
  29. Fudge string `json:"-"`
  30. GoArgs []string `json:"-"`
  31. Ret0 string `json:"-"`
  32. }
  33. type Syserror struct {
  34. Name string
  35. String string
  36. Id uint32
  37. }
  38. type Bootmethods struct {
  39. Name string
  40. Config string
  41. Connect string
  42. Arg string
  43. }
  44. type Sysconf struct {
  45. Syscalls []Syscall
  46. Syserrors []Syserror
  47. Bootmethods []Bootmethods
  48. }
  49. var mode = flag.String("mode", "", "must be one of: sys.h, sysdecl.h, syscallfiles, systab.c, error.h, errstr.h, sys_harvey.s, sysnum.go")
  50. var outpath = flag.String("o", "", "path/to/output.c")
  51. func usage(msg string) {
  52. fmt.Fprint(os.Stderr, msg)
  53. fmt.Fprint(os.Stderr, "Usage: mksys [-o outpath] -mode=MODE path/to/sysconf.json\n")
  54. flag.PrintDefaults()
  55. os.Exit(1)
  56. }
  57. func main() {
  58. flag.Parse()
  59. if flag.NArg() != 1 {
  60. usage("no path to sysconf.json")
  61. }
  62. outfile := os.Stdout
  63. if *mode != "syscallfiles" && *outpath != "" {
  64. of, err := os.Create(*outpath)
  65. if err != nil {
  66. log.Fatal(err)
  67. }
  68. outfile = of
  69. }
  70. buf, err := ioutil.ReadFile(flag.Arg(0))
  71. if err != nil {
  72. log.Fatal(err)
  73. }
  74. var sysconf Sysconf
  75. err = json.Unmarshal(buf, &sysconf)
  76. if err != nil {
  77. log.Fatal(err)
  78. }
  79. syscalls := sysconf.Syscalls
  80. syserrors := sysconf.Syserrors
  81. bootmethods := sysconf.Bootmethods
  82. for i := range syscalls {
  83. if syscalls[i].Define == "" {
  84. syscalls[i].Define = strings.ToUpper(syscalls[i].Name)
  85. }
  86. if syscalls[i].Sysname == "" {
  87. syscalls[i].Sysname = "sys" + syscalls[i].Name
  88. }
  89. if syscalls[i].Libname == "" {
  90. syscalls[i].Libname = syscalls[i].Name
  91. }
  92. }
  93. switch *mode {
  94. case "sys_harvey.s":
  95. if os.Getenv("ARCH") != "amd64" {
  96. usage("ARCH unsupported or not set")
  97. }
  98. syscallargs := []string{"DI", "SI", "DX", "R10", "R8", "R9"}
  99. //funcallregs := []string{ "DI", "SI", "DX", "CX", "R8", "R9" };
  100. for i := range syscalls {
  101. goargs := []string{}
  102. fpoff := 0
  103. for k := range syscalls[i].Args {
  104. switch syscalls[i].Args[k] {
  105. case "int32_t", "uint32_t":
  106. goargs = append(goargs, fmt.Sprintf("MOVL arg%d+%d(FP), %s", k, fpoff, syscallargs[k]))
  107. fpoff += 4
  108. case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*", "int64_t":
  109. fpoff = (fpoff + 7) & ^7
  110. goargs = append(goargs, fmt.Sprintf("MOVQ arg%d+%d(FP), %s", k, fpoff, syscallargs[k]))
  111. fpoff += 8
  112. default:
  113. log.Fatalf("unsupported arg %s in syscall: %v", syscalls[i].Args[k], syscalls[i])
  114. }
  115. }
  116. syscalls[i].GoArgs = goargs
  117. switch syscalls[i].Ret[0] {
  118. case "int32_t", "uint32_t":
  119. syscalls[i].Ret0 = fmt.Sprintf("MOVL AX, ret+%d(FP)", fpoff)
  120. fpoff += 4
  121. case "void*", "char*", "char**", "uint8_t*", "int32_t*", "uint64_t*", "int64_t*", "int64_t":
  122. fpoff = (fpoff + 7) & ^7
  123. syscalls[i].Ret0 = fmt.Sprintf("MOVQ AX, ret+%d(FP)", fpoff)
  124. fpoff += 8
  125. default:
  126. log.Fatalf("unsupported Ret[0] in syscall: %v", syscalls[i])
  127. }
  128. }
  129. tmpl, err := template.New("sys_harvey.s").Parse(`/* automatically generated by mksys */
  130. /* System calls for AMD64, Harvey */
  131. #include "go_asm.h"
  132. #include "go_tls.h"
  133. #include "textflag.h"
  134. {{ range . }}
  135. TEXT runtime·{{ .Libname }}(SB),NOSPLIT,$0
  136. {{ range .GoArgs }} {{ . }}
  137. {{ end }} MOVQ ${{ .Id }}, AX
  138. SYSCALL
  139. {{ .Ret0 }}
  140. RET
  141. {{ end }}
  142. `)
  143. if err != nil {
  144. log.Fatal(err)
  145. }
  146. err = tmpl.Execute(outfile, syscalls)
  147. if err != nil {
  148. log.Fatal(err)
  149. }
  150. case "syscallfiles":
  151. if os.Getenv("ARCH") != "amd64" {
  152. usage("ARCH unsupported or not set")
  153. }
  154. tmpl, err := template.New("syscall.s").Parse(`/* automatically generated by mksys */
  155. .globl {{ .Libname }}
  156. {{ .Libname }}:
  157. movq %rcx, %r10 /* rcx gets smashed by systenter. Use r10.*/
  158. movq ${{ .Id }},%rax /* Put the system call into rax, just like linux. */
  159. syscall
  160. ret
  161. `)
  162. if err != nil {
  163. log.Fatal(err)
  164. }
  165. for i := range syscalls {
  166. path := path.Join(*outpath, syscalls[i].Libname+".s")
  167. file, err := os.Create(path)
  168. if err != nil {
  169. log.Fatal(err)
  170. }
  171. err = tmpl.Execute(file, syscalls[i])
  172. if err != nil {
  173. log.Fatal(err)
  174. }
  175. err = file.Close()
  176. if err != nil {
  177. log.Fatal(err)
  178. }
  179. }
  180. case "sysnum.go":
  181. tmpl, err := template.New("sysnum.go").Parse(`// automatically generated by mksys
  182. package syscall
  183. const(
  184. {{ range . }} SYS_{{ .Define }} = {{ .Id }}
  185. {{ end }}
  186. )
  187. `)
  188. err = tmpl.Execute(outfile, syscalls)
  189. if err != nil {
  190. log.Fatal(err)
  191. }
  192. case "sys.h":
  193. tmpl, err := template.New("sys.h").Parse(`/* automatically generated by mksys */
  194. {{ range . }}#define {{ .Define }} {{ .Id }}
  195. {{ end }}
  196. `)
  197. err = tmpl.Execute(outfile, syscalls)
  198. if err != nil {
  199. log.Fatal(err)
  200. }
  201. case "sysdecl.h":
  202. tmpl, err := template.New("sysdecl.h").Parse(`/* automatically generated by mksys */
  203. {{ range . }}extern {{ .Ret0 }} {{ .Libname }}({{ range $i, $e := .Args }}{{ if $i }}, {{ end }}{{ $e }}{{ end }});
  204. {{ end }}
  205. `)
  206. err = tmpl.Execute(outfile, syscalls)
  207. if err != nil {
  208. log.Fatal(err)
  209. }
  210. case "systab.c":
  211. for i := range syscalls {
  212. var fudge string
  213. switch syscalls[i].Ret[0] {
  214. case "int32_t":
  215. fudge = "{ .i = -1 }"
  216. case "int64_t":
  217. fudge = "{ .vl = -1ll }"
  218. case "void*", "char*":
  219. fudge = "{ .v = (void*)-1ll }"
  220. default:
  221. log.Fatalf("unsupported Ret[0] in syscall: %v", syscalls[i])
  222. }
  223. if syscalls[i].Fudge == "" {
  224. syscalls[i].Fudge = fudge
  225. }
  226. syscalls[i].Ret0 = syscalls[i].Ret[0]
  227. }
  228. tmpl, err := template.New("systab.c").Parse(`/* automatically generated by mksys */
  229. #include "u.h"
  230. #include "../port/lib.h"
  231. #include "mem.h"
  232. #include "dat.h"
  233. #include "fns.h"
  234. #include "../../libc/9syscall/sys.h"
  235. {{ range . }}extern void {{ .Sysname }}(Ar0*, ...);
  236. {{ end }}
  237. Systab systab[] = {
  238. {{ range . }}[{{ .Define }}] { "{{ .Name }}", {{ .Sysname }}, {{ .Fudge }} },
  239. {{ end }}
  240. };
  241. int nsyscall = nelem(systab);
  242. `)
  243. err = tmpl.Execute(outfile, syscalls)
  244. if err != nil {
  245. log.Fatal(err)
  246. }
  247. case "error.h":
  248. tmpl, err := template.New("error.h").Parse(`/* automatically generated by mksys */
  249. {{ range . }}extern char {{ .Name }}[]; /* {{ .String }} */
  250. {{ end }}
  251. `)
  252. err = tmpl.Execute(outfile, syserrors)
  253. if err != nil {
  254. log.Fatal(err)
  255. }
  256. case "errstr.h":
  257. tmpl, err := template.New("errstr.h").Parse(`/* automatically generated by mksys */
  258. {{ range . }}char {{ .Name }}[] = "{{ .String }}";
  259. {{ end }}
  260. `)
  261. err = tmpl.Execute(outfile, syserrors)
  262. if err != nil {
  263. log.Fatal(err)
  264. }
  265. case "bootk8cpu.c":
  266. tmpl, err := template.New("bootk8cpu.c").Parse(`/* automatically generated by mksys */
  267. #include <u.h>
  268. #include <libc.h>
  269. #include "../boot/boot.h"
  270. Method method[] = {
  271. {{ range . }}{ "{{.Name}}", {{.Config}}, {{.Connect}}, "{{.Arg}}", },
  272. {{ end }}
  273. { nil },
  274. };
  275. int cpuflag = 1;
  276. char* rootdir = "/root";
  277. char* bootdisk = "#S/sdC0/";
  278. extern void boot(int, char**);
  279. void
  280. main(int argc, char **argv)
  281. {
  282. boot(argc, argv);
  283. }
  284. int (*cfs)(int) = 0;
  285. `)
  286. err = tmpl.Execute(outfile, bootmethods)
  287. if err != nil {
  288. log.Fatal(err)
  289. }
  290. }
  291. }