4a081501d8
- bios/conio/env/errno/gfx/io/mem/mouse/stdio/stdlib/string/sys/time/ video разложены по модулям: общие статики и helpers — в internal _-модулях (_conio.h/_mouse.h/_gfx.h/_palette.h/_atexit.h/_time.h) - lib/Makefile: LIBC_C = wildcard libc/*/*.c — гранулярность файлов = гранулярность DCE линкера - эффект _CODE: gfx_text 6986→2568 Б, gfx_mous −1745, gfx_demo/d16 −542; ранее timedir −3270, ls −3098, stattest −2995 - комментарии оставшихся модулей переведены на русский; puts: убран мёртвый pchars; videomode_raw разложен на get/set - docs/libc-split-asm-cases.md — правила asm-связок между модулями; docs/libc-roadmap.md — план этапа - восстановлен examples/mdview/SAMPLE.MD (нужен make floppy) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
73 lines
2.8 KiB
C
73 lines
2.8 KiB
C
/*
|
||
* lseek — 32-битная позиция файла через ESTEX MOVE_FP ($15).
|
||
*
|
||
* ESTEX MOVE_FP: A=handle, B=whence (0=SET, 1=CUR, 2=END),
|
||
* HL=offset high16, IX=offset low16
|
||
* возврат: HL:IX = новая абсолютная позиция, CF=err
|
||
*
|
||
* SDCC __sdcccall(1) на z80 для `long lseek(int fd, long offset, int whence)`:
|
||
* - fd — HL (первый 16-битный аргумент в регистре)
|
||
* - offset — на стеке двумя 16-битными словами (сначала low, потом high)
|
||
* - whence — на стеке (выше offset)
|
||
* - 32-битный возврат: DE = low16, HL = high16
|
||
* - стек чистит вызывающий (`pop af; pop af; pop af` после call)
|
||
*
|
||
* IX сохраняется (frame pointer вызывающего).
|
||
*/
|
||
|
||
#include <unistd.h>
|
||
|
||
long lseek(int fd, long offset, int whence) __naked
|
||
{
|
||
(void)fd; (void)offset; (void)whence;
|
||
__asm
|
||
push ix ; сохранить IX вызывающего
|
||
;; Раскладка после push:
|
||
;; SP+0..1 = сохранённый IX
|
||
;; SP+2..3 = адрес возврата
|
||
;; SP+4..5 = offset low16
|
||
;; SP+6..7 = offset high16
|
||
;; SP+8..9 = whence
|
||
|
||
ld a, l ; A = младший байт fd (был в HL)
|
||
|
||
;; 5 последовательных байтов стека читаем через HL — дешевле,
|
||
;; чем IY-индексация: `ld r,(hl); inc hl` (2Б/13Т на байт)
|
||
;; против `ld r, n(iy)` (3Б/19Т) при последовательном чтении.
|
||
ld hl, #4
|
||
add hl, sp ; HL указывает на offset_low
|
||
|
||
ld e, (hl)
|
||
inc hl
|
||
ld d, (hl) ; DE = offset_low
|
||
push de
|
||
pop ix ; IX = offset_low
|
||
inc hl
|
||
ld e, (hl)
|
||
inc hl
|
||
ld d, (hl) ; DE = offset_high
|
||
inc hl
|
||
ld b, (hl) ; B = whence (младший байт)
|
||
ex de, hl ; HL = offset_high (ESTEX ждёт его тут)
|
||
|
||
ld c, #0x15 ; ESTEX MOVE_FP
|
||
rst #0x10
|
||
jr c, _lseek_err
|
||
|
||
;; Вернулось HL:IX = новая позиция. Приводим к long-возврату
|
||
;; SDCC (DE:HL).
|
||
push ix
|
||
pop de ; DE = low16 (был IX)
|
||
;; HL уже содержит high16
|
||
pop ix ; восстановить IX вызывающего
|
||
ret
|
||
|
||
_lseek_err:
|
||
call __errno_set
|
||
ld hl, #0xFFFF
|
||
ld de, #0xFFFF ; long -1
|
||
pop ix
|
||
ret
|
||
__endasm;
|
||
}
|