ort-openrouter-cli 0.4.7

Open Router CLI
Documentation
//! ort: Open Router CLI
//! https://github.com/grahamking/ort
//!
//! MIT License
//! Copyright (c) 2025-2026 Graham King
//!
//! These are usually provided by libc.

// fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8
// rdi = dest, rsi = src, rdx = n
// we do not touch any callee save registers
.global memcpy
memcpy:
	mov rax, rdi	// we must return dest, but rep movsb will move it
	// dest already in rdi
	// src already in rsi
	mov rcx, rdx	// rcx = n
	rep movsb
	ret

// fn memset(dest: *mut u8, c: i32, count: usize) -> *mut u8
// rdi = dest, rsi = c, rdx = count
// we do not touch any callee save registers
.global memset
memset:
	mov r8, rdi		// we must return dest, but rep stosb will move it
	mov eax, esi	// eax = c (only al is used), the byte to write
	mov rcx, rdx	// rcx = count
	rep stosb
	mov rax, r8		// return dest
	ret

// fn strlen(s *const c_char) -> usize
// rdi = s
// we do not touch any callee save registers
.global strlen
strlen:
	xor eax, eax	// search for byte 0
	mov rcx, -1		// loop counter. use max for unbounded scan.
	repne scasb
	// for length n, after the loop we have subtracted n+1 from rcx (+1 for the \0 byte)
	// so rcx = -1 - (n + 1) = -(n + 2)
	// in two's complement the inverse of -(n + 1) is n
	// so ...
	not rcx			// inverse
	dec rcx			// it was n + 2 not n + 1, so decrement
	mov rax, rcx	// length is in rcx, return it
	ret

// fn bcmp(s1: *const u8, s2: *const u8, n: usize) -> i32
// rdi = s1, rsi = s2, rdx = n
//
// bcmp is a simpler version of memcmp. llvm will call this instead
// of memcmp when it can.
// we do not touch any callee save registers
.global bcmp
bcmp:
	test rdx, rdx // if n == 0
	je .Lbcmp_zero

	mov rcx, rdx	// rcx = n
	repe cmpsb
	setne al		// check ZF (zero-flag). set al to 1 if the arrays are not equal.
	movzx eax, al	// zero-extend eax from al
	ret
.Lbcmp_zero:
	xor eax, eax
	ret

// fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32
// rdi = s1, rsi = s2, rdx = n
// we do not touch any callee save registers
.global memcmp
memcmp:
	test rdx, rdx // if n == 0
	je .Lmemcmp_same

	mov rcx, rdx		// rcx = n
	repe cmpsb

	// arrays match
	je .Lmemcmp_same

	// arrays differ, figure out sign, into eax
	movzx eax, byte ptr [rdi - 1]
	movzx edx, byte ptr [rsi - 1]
	sub eax, edx
	ret

.Lmemcmp_same:
	xor eax, eax		// return 0, arrays match
	ret

// fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8
// rdi = dest, rsi = src, rdx = n
// we do not touch any callee save registers
.global memmove
memmove:
	mov    rax, rdi		// save dest, we have to return it at end

	// if src == dest
	cmp    rdi, rsi
	je     .Lmemmove_ret

	// if n == 0
	test   rdx, rdx
	je     .Lmemmove_ret

	// copy forward if dest < src
	cmp rdi, rsi
	jb .Lmemmove_forward		// jump if below

	// copy forward if dest >= src but they don't overlap
	// if dest - src >= n
	mov rcx, rdi
	sub rcx, rsi
	cmp rcx, rdx
	jae .Lmemmove_forward	// jump if above or equal

	// they overlap, copy backwards
	//
	// move pointers to the end
	lea    rdi, [rax+rdx*1-0x1]	// rdi = dest + n - 1
	lea    rsi, [rsi+rdx*1-0x1]	// rsi = src + n - 1
	mov    rcx, rdx				// rcx = n
	std							// set direction flag, we copy backwards from end
	rep movsb					// copy
	cld							// clear direction flag
	jmp    .Lmemmove_ret

.Lmemmove_forward:
	mov    rdi, rax	// restore rdi = dest
	mov    rcx, rdx	// rcx = n
	rep movsb		// copy
.Lmemmove_ret:
	// rax already has rdi, which we return
	ret