summaryrefslogtreecommitdiffstats
path: root/src/json.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/json.S')
-rw-r--r--src/json.S482
1 files changed, 482 insertions, 0 deletions
diff --git a/src/json.S b/src/json.S
new file mode 100644
index 0000000..58c5077
--- /dev/null
+++ b/src/json.S
@@ -0,0 +1,482 @@
+#include "abi.inc"
+#include "defs.inc"
+
+#define JBUF -72
+
+ .text
+
+FUNC cepis__js_ws
+.Lws_loop:
+ movzbl (%rdi), %eax
+ cmp $' ', %al
+ je .Lws_adv
+ cmp $9, %al
+ jb .Lws_end
+ cmp $13, %al
+ jbe .Lws_adv
+.Lws_end:
+ mov %rdi, %rax
+ ret
+.Lws_adv:
+ inc %rdi
+ jmp .Lws_loop
+ENDFUNC cepis__js_ws
+
+FUNC cepis__js_hex4
+ xor %ecx, %ecx
+ mov $4, %r8d
+.Lhex_loop:
+ movzbl (%rdi), %eax
+ inc %rdi
+ cmp $'0', %al
+ jb .Lhex_bad
+ cmp $'9', %al
+ jbe .Lhex_digit
+ or $0x20, %al
+ cmp $'a', %al
+ jb .Lhex_bad
+ cmp $'f', %al
+ ja .Lhex_bad
+ sub $('a' - 10), %eax
+ jmp .Lhex_acc
+.Lhex_digit:
+ sub $'0', %eax
+.Lhex_acc:
+ shl $4, %ecx
+ or %eax, %ecx
+ dec %r8d
+ jnz .Lhex_loop
+ mov %ecx, %eax
+ ret
+.Lhex_bad:
+ mov $-1, %eax
+ ret
+ENDFUNC cepis__js_hex4
+
+FUNC cepis__js_raw_string
+ cmpb $'"', (%rdi)
+ jne .Lraw_bad
+ inc %rdi
+.Lraw_loop:
+ movzbl (%rdi), %eax
+ test %al, %al
+ jz .Lraw_bad
+ cmp $'\\', %al
+ je .Lraw_esc
+ cmp $'"', %al
+ je .Lraw_close
+ inc %rdi
+ jmp .Lraw_loop
+.Lraw_esc:
+ cmpb $0, 1(%rdi)
+ je .Lraw_bad
+ add $2, %rdi
+ jmp .Lraw_loop
+.Lraw_close:
+ lea 1(%rdi), %rax
+ ret
+.Lraw_bad:
+ xor %eax, %eax
+ ret
+ENDFUNC cepis__js_raw_string
+
+FUNC cepis__js_skip
+ PROLOGUE 8
+ call cepis__js_ws
+ mov %rax, %rbx
+ movzbl (%rbx), %eax
+ test %al, %al
+ jz .Lskip_bad
+ cmp $'"', %al
+ je .Lskip_str
+ cmp $'{', %al
+ je .Lskip_nest
+ cmp $'[', %al
+ je .Lskip_nest
+ jmp .Lskip_token
+.Lskip_str:
+ mov %rbx, %rdi
+ call cepis__js_raw_string
+ EPILOGUE
+ ret
+.Lskip_token:
+ mov %rbx, %r12
+.Lskip_token_loop:
+ movzbl (%r12), %eax
+ cmp $'0', %al
+ jb .Lskip_token_sym
+ cmp $'9', %al
+ jbe .Lskip_token_adv
+ or $0x20, %al
+ cmp $'a', %al
+ jb .Lskip_token_end
+ cmp $'z', %al
+ jbe .Lskip_token_adv
+ jmp .Lskip_token_end
+.Lskip_token_sym:
+ cmp $'+', %al
+ je .Lskip_token_adv
+ cmp $'-', %al
+ je .Lskip_token_adv
+ cmp $'.', %al
+ je .Lskip_token_adv
+ jmp .Lskip_token_end
+.Lskip_token_adv:
+ inc %r12
+ jmp .Lskip_token_loop
+.Lskip_token_end:
+ cmp %rbx, %r12
+ je .Lskip_bad
+ mov %r12, %rax
+ EPILOGUE
+ ret
+.Lskip_nest:
+ xor %r13d, %r13d
+.Lskip_nest_loop:
+ movzbl (%rbx), %eax
+ test %al, %al
+ jz .Lskip_bad
+ cmp $'"', %al
+ je .Lskip_nest_str
+ cmp $'{', %al
+ je .Lskip_nest_open
+ cmp $'[', %al
+ je .Lskip_nest_open
+ cmp $'}', %al
+ je .Lskip_nest_close
+ cmp $']', %al
+ je .Lskip_nest_close
+ inc %rbx
+ jmp .Lskip_nest_loop
+.Lskip_nest_str:
+ mov %rbx, %rdi
+ call cepis__js_raw_string
+ test %rax, %rax
+ jz .Lskip_bad
+ mov %rax, %rbx
+ jmp .Lskip_nest_loop
+.Lskip_nest_open:
+ inc %r13d
+ inc %rbx
+ jmp .Lskip_nest_loop
+.Lskip_nest_close:
+ dec %r13d
+ inc %rbx
+ test %r13d, %r13d
+ jz .Lskip_nest_done
+ jmp .Lskip_nest_loop
+.Lskip_nest_done:
+ mov %rbx, %rax
+ EPILOGUE
+ ret
+.Lskip_bad:
+ xor %eax, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis__js_skip
+
+FUNC cepis__js_string
+ PROLOGUE 40
+ mov %rsi, %r14
+ movq $0, JBUF(%rbp)
+ movq $0, JBUF+8(%rbp)
+ movq $0, JBUF+16(%rbp)
+ movq $0, (%r14)
+ cmpb $'"', (%rdi)
+ jne .Lstr_fail
+ lea 1(%rdi), %rbx
+.Lstr_loop:
+ movzbl (%rbx), %eax
+ test %al, %al
+ jz .Lstr_fail
+ cmp $'"', %al
+ je .Lstr_done
+ cmp $'\\', %al
+ je .Lstr_esc
+ lea JBUF(%rbp), %rdi
+ movzbl (%rbx), %esi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+ inc %rbx
+ jmp .Lstr_loop
+.Lstr_esc:
+ movzbl 1(%rbx), %eax
+ test %al, %al
+ jz .Lstr_fail
+ cmp $'u', %al
+ je .Lstr_uesc
+ mov %eax, %r12d
+ cmp $'"', %al
+ je .Lstr_emit
+ cmp $'\\', %al
+ je .Lstr_emit
+ cmp $'/', %al
+ je .Lstr_emit
+ cmp $'b', %al
+ je .Lstr_bs
+ cmp $'f', %al
+ je .Lstr_ff
+ cmp $'n', %al
+ je .Lstr_nl
+ cmp $'r', %al
+ je .Lstr_cr
+ cmp $'t', %al
+ je .Lstr_tab
+ jmp .Lstr_fail
+.Lstr_bs:
+ mov $8, %r12d
+ jmp .Lstr_emit
+.Lstr_ff:
+ mov $12, %r12d
+ jmp .Lstr_emit
+.Lstr_nl:
+ mov $10, %r12d
+ jmp .Lstr_emit
+.Lstr_cr:
+ mov $13, %r12d
+ jmp .Lstr_emit
+.Lstr_tab:
+ mov $9, %r12d
+.Lstr_emit:
+ lea JBUF(%rbp), %rdi
+ mov %r12d, %esi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+ add $2, %rbx
+ jmp .Lstr_loop
+.Lstr_uesc:
+ lea 2(%rbx), %rdi
+ call cepis__js_hex4
+ test %eax, %eax
+ js .Lstr_fail
+ mov %eax, %r12d
+ add $6, %rbx
+ cmp $0xD800, %r12d
+ jb .Lstr_encode
+ cmp $0xDBFF, %r12d
+ ja .Lstr_low
+ cmpb $'\\', (%rbx)
+ jne .Lstr_repl
+ cmpb $'u', 1(%rbx)
+ jne .Lstr_repl
+ lea 2(%rbx), %rdi
+ call cepis__js_hex4
+ test %eax, %eax
+ js .Lstr_repl
+ mov %eax, %r13d
+ cmp $0xDC00, %r13d
+ jb .Lstr_repl
+ cmp $0xDFFF, %r13d
+ ja .Lstr_repl
+ add $6, %rbx
+ sub $0xD800, %r12d
+ shl $10, %r12d
+ sub $0xDC00, %r13d
+ add %r13d, %r12d
+ add $0x10000, %r12d
+ jmp .Lstr_encode
+.Lstr_low:
+ cmp $0xDFFF, %r12d
+ ja .Lstr_encode
+.Lstr_repl:
+ mov $0xFFFD, %r12d
+.Lstr_encode:
+ cmp $0x80, %r12d
+ jb .Lstr_enc1
+ cmp $0x800, %r12d
+ jb .Lstr_enc2
+ cmp $0x10000, %r12d
+ jb .Lstr_enc3
+ mov %r12d, %esi
+ shr $18, %esi
+ or $0xF0, %esi
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+ mov %r12d, %esi
+ shr $12, %esi
+ and $0x3F, %esi
+ or $0x80, %esi
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+ jmp .Lstr_enc_tail2
+.Lstr_enc3:
+ mov %r12d, %esi
+ shr $12, %esi
+ or $0xE0, %esi
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+.Lstr_enc_tail2:
+ mov %r12d, %esi
+ shr $6, %esi
+ and $0x3F, %esi
+ or $0x80, %esi
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+ jmp .Lstr_enc_tail1
+.Lstr_enc2:
+ mov %r12d, %esi
+ shr $6, %esi
+ or $0xC0, %esi
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+.Lstr_enc_tail1:
+ mov %r12d, %esi
+ and $0x3F, %esi
+ or $0x80, %esi
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+ jmp .Lstr_loop
+.Lstr_enc1:
+ mov %r12d, %esi
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_appendc
+ test %eax, %eax
+ jnz .Lstr_fail
+ jmp .Lstr_loop
+.Lstr_done:
+ inc %rbx
+ cmpq $0, JBUF(%rbp)
+ jne .Lstr_take
+ call cepis__empty
+ test %rax, %rax
+ jz .Lstr_fail
+ mov %rax, (%r14)
+ mov %rbx, %rax
+ EPILOGUE
+ ret
+.Lstr_take:
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_take
+ mov %rax, (%r14)
+ mov %rbx, %rax
+ EPILOGUE
+ ret
+.Lstr_fail:
+ lea JBUF(%rbp), %rdi
+ call cepis__buf_free
+ movq $0, (%r14)
+ xor %eax, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis__js_string
+
+FUNC cepis__js_scalar_text
+ PROLOGUE 24
+ mov %rsi, %r14
+ movq $0, (%r14)
+ call cepis__js_ws
+ mov %rax, %rbx
+ movzbl (%rbx), %eax
+ cmp $'"', %al
+ je .Lsc_string
+ cmp $'{', %al
+ je .Lsc_fail
+ cmp $'[', %al
+ je .Lsc_fail
+ mov %rbx, %rdi
+ call cepis__js_skip
+ test %rax, %rax
+ jz .Lsc_fail
+ mov %rax, %r12
+ mov %r12, %r13
+ sub %rbx, %r13
+ cmp $4, %r13
+ jne .Lsc_copy
+ mov %rbx, %rdi
+ lea .Lsc_null(%rip), %rsi
+ mov $4, %rdx
+ call memcmp@PLT
+ test %eax, %eax
+ jnz .Lsc_copy
+ call cepis__empty
+ test %rax, %rax
+ jz .Lsc_fail
+ mov %rax, (%r14)
+ mov %r12, %rax
+ EPILOGUE
+ ret
+.Lsc_copy:
+ mov %rbx, %rdi
+ mov %r13, %rsi
+ call cepis__strndup
+ test %rax, %rax
+ jz .Lsc_fail
+ mov %rax, (%r14)
+ mov %r12, %rax
+ EPILOGUE
+ ret
+.Lsc_string:
+ mov %rbx, %rdi
+ mov %r14, %rsi
+ call cepis__js_string
+ EPILOGUE
+ ret
+.Lsc_fail:
+ xor %eax, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis__js_scalar_text
+
+FUNC cepis__js_number
+ PROLOGUE 40
+ mov %rsi, %r14
+ call cepis__js_ws
+ mov %rax, %rbx
+ cmpb $'"', (%rbx)
+ je .Lnum_quoted
+ mov %rbx, %rdi
+ lea LOCAL0(%rbp), %rsi
+ call strtod@PLT
+ mov LOCAL0(%rbp), %rax
+ cmp %rbx, %rax
+ je .Lnum_fail
+ movsd %xmm0, (%r14)
+ EPILOGUE
+ ret
+.Lnum_quoted:
+ mov %rbx, %rdi
+ lea LOCAL1(%rbp), %rsi
+ call cepis__js_string
+ test %rax, %rax
+ jz .Lnum_fail
+ mov %rax, %r12
+ mov LOCAL1(%rbp), %rdi
+ lea LOCAL0(%rbp), %rsi
+ call strtod@PLT
+ movsd %xmm0, LOCAL2(%rbp)
+ mov LOCAL1(%rbp), %rbx
+ mov LOCAL0(%rbp), %r13
+ mov %rbx, %rdi
+ call free@PLT
+ cmp %rbx, %r13
+ je .Lnum_fail
+ movsd LOCAL2(%rbp), %xmm0
+ movsd %xmm0, (%r14)
+ mov %r12, %rax
+ EPILOGUE
+ ret
+.Lnum_fail:
+ xor %eax, %eax
+ EPILOGUE
+ ret
+ENDFUNC cepis__js_number
+
+ .section .rodata
+.Lsc_null:
+ .ascii "null"
+
+ .section .note.GNU-stack,"",@progbits