PDA

Просмотр полной версии : ABS и SGN в машкоде



Oleg N. Cher
01.01.2017, 15:06
Всем привет.
Покритикуйте мою реализацию функций ABS и SGN для байта и слова, может можно как-то оптимизировать.
Байтовый аргумент поступает в регистре L, результат возвращается в нём же. Слова - в паре HL. Таковы соглашения модели вызова __z88dk_fastcall.


/*--------------------------------- Cut here ---------------------------------*/
signed char Basic_ABS (signed char x) __z88dk_fastcall {
__asm
BIT 7,L
RET Z
XOR A
SUB L
LD L,A
__endasm;
} //Basic_ABS

/*--------------------------------- Cut here ---------------------------------*/
signed int Basic_ABSI (signed int x) __z88dk_fastcall {
__asm
BIT 7,H
RET Z
EX DE,HL
XOR A
LD L,A
LD H,A
SBC HL,DE
__endasm;
} //Basic_ABSI

/*--------------------------------- Cut here ---------------------------------*/
signed char Basic_SGN (signed char x) __z88dk_fastcall {
__asm
LD A,L
OR L
RET Z
BIT 7,L
LD L,#0xFF
RET NZ
LD L,#1
__endasm;
} //Basic_SGN

/*--------------------------------- Cut here ---------------------------------*/
signed char Basic_SGNI (signed int x) __z88dk_fastcall {
__asm
LD A,H
OR L
RET Z
BIT 7,H
LD L,#0xFF
RET NZ
LD L,#1
__endasm;
} //Basic_SGNI

SaNchez
01.01.2017, 15:35
Идеально, оптимизировать нечего ;)

Alex Rider
01.01.2017, 15:46
XOR A
LD L,A
LD H,A





LD L,0
LD H,L

На такт быстрее.

SaNchez
01.01.2017, 15:47
Не обнулил флаг C.

Alex Rider
01.01.2017, 16:05
Точно :-(

NEO SPECTRUMAN
01.01.2017, 17:51
bit 7,h ;8
ret z ;5 11

ex de,hl ;4
xor a ;4
ld l,a ;4
ld h,a ;4
sbc hl,de ;15
ret ;10

;19 54 оригинальная процедура



bit 7,h ;8
ret z ;5 11

ld a,h ;4
cpl ;4
ld h,a ;4
ld a,l ;4
cpl ;4
ld l,a ;4
inc hl ;6
ret ;10

;19 53



ld a,h ;4
cp $80 ;7 возможно +-$01
ret c ;5 11

cpl ;4
ld h,a ;4
ld a,l ;4
cpl ;4
ld l,a ;4
inc hl ;6
ret ;10

;22 52


- - - Добавлено - - -




XOR A
LD L,A
LD H,A

LD L,0
LD H,L

На такт быстрее.

LD HL,$0000 в таком случае на 2 такта быстрее;)

Titus
01.01.2017, 18:28
Не проверял. На вскидку так:


LD A,H ; 4
OR A ; 4
RET P ; 5 / 11

CPL ; 4
LD H,A ; 4
LD A,L ; 4
CPL ; 4
LD L,A ; 4
INC HL ; 6
RET ; 10

; 19 / 49


LD A,$FF ; 7
XOR H ; 4
RET M ; 5 / 11

LD H,A ; 4
LD A,L ; 4
CPL ; 4
LD L,A ; 4
INC HL ; 6
RET ; 10

; 22 / 48

NEO SPECTRUMAN
01.01.2017, 20:58
SGN можно запилить 100500-ю способами



;оригинальная процедура
LD A,L ;4
OR L ;4
RET Z ;5 11
BIT 7,L ;8
LD L,#0xFF ;7
RET NZ ;5 11
LD L,#1 ;7
RET ;10
;+=50 0=19 -=39
;36 в среднем ; 44,5 в среднем без 0


с ходу придумалось так


ld a,l ;4
rlca ;4 возможно rla (нужно чтоб флаг С не попадал в А)

jp c,l1 ;10 (7 12 JR)

or a ;4
ret z ;5 11
ld l,$01 ;7
ret ;10

l1
ld l,$FF ;7
ret ;10

;с использованием JP
;+=44 0=33 -=35
;37,3 в среднем ;39,5 в среднем без 0

;с использованием JR
;+=41 0=30 -=37
;36 в среднем ; 39 в среднем без 0

думаю можно и в 600 раз быстрее как минимум
кажется мне оптимизировать процедуру чтоб проверка на 0(1 против 255 других входящих значений) выполнялась быстрей всего нет смысла
правда я хз в какой ситуации применять sgn

- - - Добавлено - - -


вы и правда так кодите

мну *****кодер 80 уровня

Я только сегодня узнал что такое sgn:rolleyes:
глядя на код в самом верху:D

кто мне не дает так кодить?

- - - Добавлено - - -

MOAR SPEED!!!


rlc l ;8
ret z ;5 11

jp c,l1 ;10 (7 12 JR)
ld l,$01 ;7
ret ;10

l1
ld l,$FF ;7
ret ;10

;с использованием JP
;+=40 0=19 -=40
;33 в среднем ;40 в среднем без 0

;с использованием JR
;+=37 0=19 -=42
;32,6 в среднем ;39,5 в среднем без 0


АND MOAR!!!!


rlc l ;8
ret z ;5 11

ld l,$01 ;7 ;ld l,$FF

ret nc ;5 11 ;ret c

ld l,$FF ;7 ;ld l,$01
ret ;10

;-=31 0=19 +=42
;30,6 в среднем ;36,5 в среднем без 0

;легко реверсится в
;-=42 0=19 +=31 (если положительные числа встречаются чаще(а они наверное встречаются чаще))



- - - Добавлено - - -




;оригинальная процедура
BIT 7,L 8
RET Z 5 11
XOR A 4
SUB L 4
LD L,A 4
RET 10
;19 35





xor a ;4
sub l ;4
ret m ;5 11

ld l,a ;4
ret ;10

;19 27
;по ходу дает ложный результат при $00 и $80 перепроверьте кто нить!!!

Oleg N. Cher
02.01.2017, 01:33
А какой результат должно дать ABS($80)? Разве не $80? Просто у него нет симметричного положительного :-)

- - - Добавлено - - -


/*--------------------------------- Cut here ---------------------------------*/
signed char Basic_SGN (signed char x) __z88dk_fastcall { // Code by NEO SPECTRUMAN
__asm
RLC L ; 8
RET Z ; 5 11
LD L,#1 ; 7
RET NC ; 5 11
LD L,#0xFF ; 7
__endasm;
} //Basic_SGN
NEO SPECTRUMAN, зачётный код, респект! Я бы так не додумался. :-) Вот что значит опыт низкоуровневого кодинга. У меня он небольшой. Интересно, как бы Вы оптимизировали Laser2 :-)

char
02.01.2017, 04:02
;sgn

rlc l
ret z
sbc a,a
ld l,a
set 0,l


+
jr nc, -> 0..127
jr c, -> -128..-1

SaNchez
02.01.2017, 04:26
;sgn
+
jr nc, -> 0..127
jr c, -> -128..-1

Если переходы не нужны, то можно еще такт сэкономить:


rlc l
ret z
sbc a,a
or 1
ld l,a

Oleg N. Cher
02.01.2017, 06:37
Что значит "если переходы не нужны"? :-)

SaNchez
02.01.2017, 06:55
char предложил общий вариант, но если использовать только для функции, можно один такт выиграть, поменяв "set 0,l" на "or 1".

signed char Basic_SGN (signed char x) __z88dk_fastcall {
__asm
RLC L
RET Z
SBC A,A
OR 1
LD L,A
__endasm;
} //Basic_SGN

char
02.01.2017, 08:23
хотите линейную, и самую жесть? их есть у нас ->

ld a,l
rla
sbc a,a
sub l
adc a,l
ld l,a

SaNchez
02.01.2017, 08:48
Гениально! :v2_dizzy_roll:

Titus
02.01.2017, 11:02
хотите линейную, и самую жесть? их есть у нас ->

ld a,l
rla
sbc a,a3
sub l
adc a,l
ld l,a
Пиши демы)

char
02.01.2017, 11:34
Пиши демы)

как только, так... уже )

для себя вынес из темы "две новейших двадцатитактных команды", еще бы знать куда их теперь... )

;sgn c
ld a,c
rla
sbc a,a
sub c
adc a,c

;sgn c,a
ld c,a
rla
sbc a,a
sub c
adc a,c

Titus
02.01.2017, 14:48
как только, так... уже )
Как называются?

Oleg N. Cher
04.01.2017, 03:55
Titus, только доглядел. Это мега-код! :-) По сравнению с оригинальной процедурой:

signed int Basic_ABSI (signed int x) __z88dk_fastcall {
__asm
BIT 7,H ; 8
RET Z ; 11/5
EX DE,HL ; 4
XOR A ; 4
LD L,A ; 4
LD H,A ; 4
SBC HL,DE ; 15 => 44/19
__endasm;
} //Basic_ABSI
Получилось:

signed int Basic_ABSI (signed int x) __z88dk_fastcall {
__asm // Code by Titus
LD A,H ; 4
OR A ; 4
RET P ; 11/5
CPL ; 4
LD H,A ; 4
LD A,L ; 4
CPL ; 4
LD L,A ; 4
INC HL ; 6 => 39/19
__endasm;
} //Basic_ABSIТактов кушает меньше и не портит пару DE! А байтиков столько же!

В Basic.h добавляю ключик:

extern signed int Basic_ABSI (signed int x) __z88dk_fastcall __preserves_regs(b,c,d,e,iyl,iyh);- и оптимизатор точно знает, какие регистры сохраняет функция. И использует эту информацию, чтобы сделать код лучше.

- - - Добавлено - - -

Эх, всё-таки не зря открыл тему =) Благодарю!

Oleg N. Cher
10.01.2017, 04:14
На идеях char'а и SaNchez'а. SGN для байтов:


signed char Basic_SGN (signed char x) __z88dk_fastcall {
__asm // Code by char & SaNchez
RLC L
RET Z
SBC A
OR #1
LD L,A
__endasm;
} //Basic_SGNДля слов:

signed char Basic_SGNI (signed int x) __z88dk_fastcall {
__asm // Code by char & SaNchez
LD A,L
OR H
RET Z
RLC H
SBC A
OR #1
LD L,A
__endasm;
} //Basic_SGNI