summary refs log tree commit diff stats
path: root/lib/arch/unix_amd64.asm
blob: 3005c150c0aaabd98b3b7d6d34ef30b880094bdb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
;
;
;            Nim's Runtime Library
;        (c) Copyright 2015 Rokas Kupstys
;
;    See the file "copying.txt", included in this
;    distribution, for details about the copyright.
;

format ELF64

section ".text" executable align 16
public narch_getRegisters
public narch_setjmp
public narch_longjmp
public narch_coroSwitchStack
public narch_coroRestoreStack


narch_getRegisters:
    mov   [rdi], rax
    mov   [rdi+8], rbx
    mov   [rdi+10h], rcx
    mov   [rdi+18h], rdx
    mov   [rdi+20h], rsi
    mov   [rdi+28h], rdi
    mov   [rdi+30h], rbp
    mov   [rdi+38h], rsp
    mov   rax, [rsp]
    mov   [rdi+40h], rax      ; rip
    mov   [rdi+48h], r8
    mov   [rdi+50h], r9
    mov   [rdi+58h], r10
    mov   [rdi+60h], r11
    mov   [rdi+68h], r12
    mov   [rdi+70h], r13
    mov   [rdi+78h], r14
    mov   [rdi+80h], r15
    ret


narch_setjmp:
    ; Based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
    mov   [rdi], rbx          ; rdi is jmp_buf, move registers onto it
    mov   [rdi+8], rbp
    mov   [rdi+10h], r12
    mov   [rdi+18h], r13
    mov   [rdi+20h], r14
    mov   [rdi+28h], r15
    lea   rdx, [rsp+8]        ; this is our rsp WITHOUT current ret addr
    mov   [rdi+30h], rdx
    mov   rdx, [rsp]          ; save return addr ptr for new rip
    mov   [rdi+38h], rdx
    xor   rax, rax            ; always return 0
    ret


narch_longjmp:
    ; Based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
    mov   rax, rsi            ; val will be longjmp return
    test  rax, rax
    jnz   @F
    inc   rax                 ; if val==0, val=1 per longjmp semantics
@@:
    mov   rbx, [rdi]          ; rdi is the jmp_buf, restore regs from it
    mov   rbp, [rdi+8]
    mov   r12, [rdi+10h]
    mov   r13, [rdi+18h]
    mov   r14, [rdi+20h]
    mov   r15, [rdi+28h]
    mov   rsp, [rdi+30h]      ; this ends up being the stack pointer
    mov   rdx, [rdi+38h]      ; this is the instruction pointer
    jmp   rdx                 ; goto saved address without altering rsp


narch_coroSwitchStack:
    pop rsi                   ; return address
    mov rdx, rsp              ; old rsp for saving
    mov rsp, rdi              ; swap stack with one passed to func
    push rdx                  ; store old stack pointer on newly switched stack
    sub rsp, 8h               ; stack alignment
    jmp rsi                   ; return


narch_coroRestoreStack:
	pop rsi                   ; return address
	add rsp, 8h               ; stack alignment
	pop rsp                   ; resture old stack pointer
	jmp rsi                   ; return
"> skinEndX: InternalError("parser to implement") result = ast.emptyNode #skinEndX: result := pendx.parseTopLevelStmt(p.parser); proc UTF8_BOM(s: string): int = if (s[0] == '\xEF') and (s[1] == '\xBB') and (s[2] == '\xBF'): result = 3 else: result = 0 proc containsShebang(s: string, i: int): bool = if (s[i] == '#') and (s[i + 1] == '!'): var j = i + 2 while s[j] in WhiteSpace: inc(j) result = s[j] == '/' proc parsePipe(filename: string, inputStream: PLLStream): PNode = result = ast.emptyNode var s = LLStreamOpen(filename, fmRead) if s != nil: var line = newStringOfCap(80) discard LLStreamReadLine(s, line) var i = UTF8_Bom(line) if containsShebang(line, i): discard LLStreamReadLine(s, line) i = 0 if line[i] == '#' and line[i+1] == '!': inc(i, 2) while line[i] in WhiteSpace: inc(i) var q: TParser OpenParser(q, filename, LLStreamOpen(substr(line, i))) result = parser.parseAll(q) CloseParser(q) LLStreamClose(s) proc getFilter(ident: PIdent): TFilterKind = for i in countup(low(TFilterKind), high(TFilterKind)): if IdentEq(ident, filterNames[i]): return i result = filtNone proc getParser(ident: PIdent): TParserKind = for i in countup(low(TParserKind), high(TParserKind)): if IdentEq(ident, parserNames[i]): return i rawMessage(errInvalidDirectiveX, ident.s) proc getCallee(n: PNode): PIdent = if n.kind in nkCallKinds and n.sons[0].kind == nkIdent: result = n.sons[0].ident elif n.kind == nkIdent: result = n.ident else: rawMessage(errXNotAllowedHere, renderTree(n)) proc applyFilter(p: var TParsers, n: PNode, filename: string, stdin: PLLStream): PLLStream = var ident = getCallee(n) var f = getFilter(ident) case f of filtNone: p.skin = getParser(ident) result = stdin of filtTemplate: result = filterTmpl(stdin, filename, n) of filtStrip: result = filterStrip(stdin, filename, n) of filtReplace: result = filterReplace(stdin, filename, n) if f != filtNone: if gVerbosity >= 2: rawMessage(hintCodeBegin, []) MsgWriteln(result.s) rawMessage(hintCodeEnd, []) proc evalPipe(p: var TParsers, n: PNode, filename: string, start: PLLStream): PLLStream = result = start if n.kind == nkEmpty: return if (n.kind == nkInfix) and (n.sons[0].kind == nkIdent) and IdentEq(n.sons[0].ident, "|"): for i in countup(1, 2): if n.sons[i].kind == nkInfix: result = evalPipe(p, n.sons[i], filename, result) else: result = applyFilter(p, n.sons[i], filename, result) elif n.kind == nkStmtList: result = evalPipe(p, n.sons[0], filename, result) else: result = applyFilter(p, n, filename, result) proc openParsers(p: var TParsers, filename: string, inputstream: PLLStream) = var s: PLLStream p.skin = skinStandard var pipe = parsePipe(filename, inputStream) if pipe != nil: s = evalPipe(p, pipe, filename, inputStream) else: s = inputStream case p.skin of skinStandard, skinBraces, skinEndX: parser.openParser(p.parser, filename, s) proc closeParsers(p: var TParsers) = parser.closeParser(p.parser)