173 lines
2.8 KiB
ArmAsm
173 lines
2.8 KiB
ArmAsm
// SPDX-License-Identifier: GPL-2.0-only
|
|
// Copyright (C) 2015-2021 ARM Limited.
|
|
// Original author: Dave Martin <Dave.Martin@arm.com>
|
|
//
|
|
// Utility functions for assembly code.
|
|
|
|
#include <asm/unistd.h>
|
|
#include "assembler.h"
|
|
|
|
// Print a single character x0 to stdout
|
|
// Clobbers x0-x2,x8
|
|
function putc
|
|
str x0, [sp, #-16]!
|
|
|
|
mov x0, #1 // STDOUT_FILENO
|
|
mov x1, sp
|
|
mov x2, #1
|
|
mov x8, #__NR_write
|
|
svc #0
|
|
|
|
add sp, sp, #16
|
|
ret
|
|
endfunction
|
|
.globl putc
|
|
|
|
// Print a NUL-terminated string starting at address x0 to stdout
|
|
// Clobbers x0-x3,x8
|
|
function puts
|
|
mov x1, x0
|
|
|
|
mov x2, #0
|
|
0: ldrb w3, [x0], #1
|
|
cbz w3, 1f
|
|
add x2, x2, #1
|
|
b 0b
|
|
|
|
1: mov w0, #1 // STDOUT_FILENO
|
|
mov x8, #__NR_write
|
|
svc #0
|
|
|
|
ret
|
|
endfunction
|
|
.globl puts
|
|
|
|
// Print an unsigned decimal number x0 to stdout
|
|
// Clobbers x0-x4,x8
|
|
function putdec
|
|
mov x1, sp
|
|
str x30, [sp, #-32]! // Result can't be > 20 digits
|
|
|
|
mov x2, #0
|
|
strb w2, [x1, #-1]! // Write the NUL terminator
|
|
|
|
mov x2, #10
|
|
0: udiv x3, x0, x2 // div-mod loop to generate the digits
|
|
msub x0, x3, x2, x0
|
|
add w0, w0, #'0'
|
|
strb w0, [x1, #-1]!
|
|
mov x0, x3
|
|
cbnz x3, 0b
|
|
|
|
ldrb w0, [x1]
|
|
cbnz w0, 1f
|
|
mov w0, #'0' // Print "0" for 0, not ""
|
|
strb w0, [x1, #-1]!
|
|
|
|
1: mov x0, x1
|
|
bl puts
|
|
|
|
ldr x30, [sp], #32
|
|
ret
|
|
endfunction
|
|
.globl putdec
|
|
|
|
// Print an unsigned decimal number x0 to stdout, followed by a newline
|
|
// Clobbers x0-x5,x8
|
|
function putdecn
|
|
mov x5, x30
|
|
|
|
bl putdec
|
|
mov x0, #'\n'
|
|
bl putc
|
|
|
|
ret x5
|
|
endfunction
|
|
.globl putdecn
|
|
|
|
// Clobbers x0-x3,x8
|
|
function puthexb
|
|
str x30, [sp, #-0x10]!
|
|
|
|
mov w3, w0
|
|
lsr w0, w0, #4
|
|
bl puthexnibble
|
|
mov w0, w3
|
|
|
|
ldr x30, [sp], #0x10
|
|
// fall through to puthexnibble
|
|
endfunction
|
|
.globl puthexb
|
|
|
|
// Clobbers x0-x2,x8
|
|
function puthexnibble
|
|
and w0, w0, #0xf
|
|
cmp w0, #10
|
|
blo 1f
|
|
add w0, w0, #'a' - ('9' + 1)
|
|
1: add w0, w0, #'0'
|
|
b putc
|
|
endfunction
|
|
.globl puthexnibble
|
|
|
|
// x0=data in, x1=size in, clobbers x0-x5,x8
|
|
function dumphex
|
|
str x30, [sp, #-0x10]!
|
|
|
|
mov x4, x0
|
|
mov x5, x1
|
|
|
|
0: subs x5, x5, #1
|
|
b.lo 1f
|
|
ldrb w0, [x4], #1
|
|
bl puthexb
|
|
b 0b
|
|
|
|
1: ldr x30, [sp], #0x10
|
|
ret
|
|
endfunction
|
|
.globl dumphex
|
|
|
|
// Trivial memory copy: copy x2 bytes, starting at address x1, to address x0.
|
|
// Clobbers x0-x3
|
|
function memcpy
|
|
cmp x2, #0
|
|
b.eq 1f
|
|
0: ldrb w3, [x1], #1
|
|
strb w3, [x0], #1
|
|
subs x2, x2, #1
|
|
b.ne 0b
|
|
1: ret
|
|
endfunction
|
|
.globl memcpy
|
|
|
|
// Fill x1 bytes starting at x0 with 0xae (for canary purposes)
|
|
// Clobbers x1, x2.
|
|
function memfill_ae
|
|
mov w2, #0xae
|
|
b memfill
|
|
endfunction
|
|
.globl memfill_ae
|
|
|
|
// Fill x1 bytes starting at x0 with 0.
|
|
// Clobbers x1, x2.
|
|
function memclr
|
|
mov w2, #0
|
|
endfunction
|
|
.globl memclr
|
|
// fall through to memfill
|
|
|
|
// Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
|
|
// Clobbers x1
|
|
function memfill
|
|
cmp x1, #0
|
|
b.eq 1f
|
|
|
|
0: strb w2, [x0], #1
|
|
subs x1, x1, #1
|
|
b.ne 0b
|
|
|
|
1: ret
|
|
endfunction
|
|
.globl memfill
|