[SDK] Новая математика для кросс-компилятора в 8080/z80
Moderator: Shaos
[SDK] Новая математика для кросс-компилятора в 8080/z80
Я завожу эту новую тему в связи с тем, что мне надо заменить математику в nedoPC SDK с вынутой из Small-C 1984 года на свою (чтобы 100% библиотек SDK объявить PUBLIC DOMAIN). Планируется написать новые подпрограммы в мнемониках i8080 и z80, чтобы подменить содержимое теперешнего _CLIB.A - большинство кода будет вставляться в генерируемый ассемблер как есть (т.е. как макросы - без вызова подпрограмм), а всё ещё вызываемыми по CALL подпрограммами по-видимому останутся DIVMOD, MULT и наверное сдвиги...
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора
Подсмотрел тут у Алоне как он делает NEG HL в NedoLang:
Интересно, а можно компактнее и/или быстрее? типа
Выходит больше и дольше
Тоже...
Code: Select all
XOR A ; +4=4
SUB L ; +4=8
LD L,A ; +4=12
SBC H ; +4=16
SUB L ; +4=20
LD H,A ; +4=24
Code: Select all
LD DE,0 ; +10=10
EX DE,HL ; +4=14
OR A ; +4=18
SBC HL,DE ; +15=33
Code: Select all
LD A,H ; +4=4
CPL ; +4=8
LD H,A ; +4=12
LD A,L ; +4=16
CPL ; +4=20
LD L,A ; +4=24
INC HL ; +6=30
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
Первые ласточки - логические AND и OR (в мнемониках RASM i8080):
(они и до этого были мои самописные, но в виде подпрограмм, а теперь будут в виде макросов)
Code: Select all
// 0x80 // && A,B -> A&&B
*EXPR 0x80
#genlab %l1
POP_D
MOV_A,D
ORA_E
JZ %l1
MOV_A,H
ORA_L
JZ %l1
MVI_A, #FF
%l1
MOV_H,A
MOV_L,A
*
// 0x81 // || A,B -> A||B
*EXPR 0x81
#genlab %l1
#genlab %l2
POP_D
MOV_A,D
ORA_E
JNZ %l1
MOV_A,H
ORA_L
JZ %l2
%l1
MVI_A, #FF
%l2
MOV_H,A
MOV_L,A
*
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
Идём дальше:
P.S. 24 июля 2024 года исправил косяк в != заменив второй CMP на SUB, чтобы в регистре A пролучился 0 если байты были равны...
Code: Select all
// 0x90 // == A,B -> A==B
*EXPR 0x90
#genlab %l1
#genlab %l2
POP_D
MOV_A,H
CMP_D
JNZ %l1
MOV_A,L
CMP_E
JNZ %l1
LXI_H, #FFFF
JMP %l2
%l1
LXI_H, 0
%l2
*
// 0x91 // != A,B -> A!=B
*EXPR 0x91
#genlab %l1
#genlab %l2
POP_D
MOV_A,H
CMP_D
JNZ %l1
MOV_A,L
SUB_E
JZ %l2
%l1
MVI_A, #FF
%l2
MOV_H,A
MOV_L,A
*
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
Пользуйся Microsoft, а то какую то % пишешь. Ей богу.
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
Зачем мне пользоваться Microsoft? У них есть компилируемый язык высокого уровня для 8080?Mondx wrote:Пользуйся Microsoft, а то какую то % пишешь. Ей богу.
Или у них есть матлиба под 8080 с сомнительной лицензией и ограничениями в использовании?
Я же написал выше - мне PUBLIC DOMAIN нужен...
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
Итак, идём дальше:
Для проверки разнообразных условий я написал вот такой тест на Robby:
Этот тест компилируется в бинарник 5K с хвостиком, который успешно выполняется в эмуляторе Pseudo-86RK:
Code: Select all
// 0x92 // > A,B -> A>B
*EXPR 0x92
#genlab %l1
#genlab %l2
POP_D
MOV_A,E
SUB_L
MOV_L,A
MOV_A,D
SBB_H
MOV_H,A
ORA_L
JZ %l2
MOV_A,H
ANA_A
JM %l1
LXI_H, #FFFF
JMP %l2
%l1
LXI_H, 0
%l2
*
// 0x93 // < A,B -> A<B
*EXPR 0x93
#genlab %l1
#genlab %l2
POP_D
MOV_A,L
SUB_E
MOV_L,A
MOV_A,H
SBB_D
MOV_H,A
ORA_L
JZ %l2
MOV_A,H
ANA_A
JM %l1
LXI_H, #FFFF
JMP %l2
%l1
LXI_H, 0
%l2
*
// 0x94 // >= A,B -> A>=B
*EXPR 0x94
#genlab %l1
#genlab %l2
#genlab %l3
POP_D
MOV_A,L
SUB_E
MOV_L,A
MOV_A,H
SBB_D
MOV_H,A
ORA_L
JZ %l1
MOV_A,H
ANA_A
JP %l2
%l1
LXI_H, #FFFF
JMP %l3
%l2
LXI_H, 0
%l3
*
// 0x95 // <= A,B -> A<=B
*EXPR 0x95
#genlab %l1
#genlab %l2
#genlab %l3
POP_D
MOV_A,E
SUB_L
MOV_L,A
MOV_A,D
SBB_H
MOV_H,A
ORA_L
JZ %l1
MOV_A,H
ANA_A
JP %l2
%l1
LXI_H, #FFFF
JMP %l3
%l2
LXI_H, 0
%l3
*
Code: Select all
// CREATED: 20-JUL-2024
ROBOT "TEST-0002"
AUTHOR "SHAOS"
+INC/ROBBY
main()
{
text "<><><><><><><><><><> MAIN-BEGIN"
def arr[10] = {-1, 0, 1, 0}
EQ1 = arr[1] == arr[2]
NE1 = arr[1] != arr[2]
GT1 = arr[1] > arr[2]
GE1 = arr[1] >= arr[2]
LT1 = arr[1] < arr[2]
LE1 = arr[1] <= arr[2]
EQ2 = arr[1] == arr[0]
NE2 = arr[1] != arr[0]
GT2 = arr[1] > arr[0]
GE2 = arr[1] >= arr[0]
LT2 = arr[1] < arr[0]
LE2 = arr[1] <= arr[0]
EQ3 = arr[1] == arr[3]
NE3 = arr[1] != arr[3]
GT3 = arr[1] > arr[3]
GE3 = arr[1] >= arr[3]
LT3 = arr[1] < arr[3]
LE3 = arr[1] <= arr[3]
termsetsay(0,5,2)
say "F?#&EQ1 T?#&NE1 F?#>1 F?#&GE1 T?#<1 T?#&LE1 "
termsetsay(0,6,2)
say "F?#&EQ2 T?#&NE2 T?#>2 T?#&GE2 F?#<2 F?#&LE2 "
termsetsay(0,7,2)
say "T?#&EQ3 F?#&NE3 F?#>3 T?#&GE3 F?#<3 T?#&LE3 "
SUM = 0
if(!EQ1&&NE1) SUM=SUM+1
if(!GT1) SUM=SUM+2
if(!GE1) SUM=SUM+4
if(LT1) SUM=SUM+8
if(LE1) SUM=SUM+16
if(!EQ2&&NE2) SUM=SUM+32
if(GT2) SUM=SUM+64
if(GE2) SUM=SUM+128
if(!LT2) SUM=SUM+256
if(!LE2) SUM=SUM+512
if(EQ3&&!NE3) SUM=SUM+1024
if(!GT3) SUM=SUM+2048
if(GE3) SUM=SUM+4096
if(!LT3) SUM=SUM+8192
if(LE3) SUM=SUM+16384
termsetsay(0,10,2)
if(SUM==#7FFF) say "GOOD #&SUM "
else say "BAD #&SUM "
text "<><><><><><><><><><> MAIN-END"
}
+LIB/P2TERM
- Attachments
- Screenshot from 2024-07-20 21-39-04.png (15.52 KiB) Viewed 1032 times
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
Code: Select all
// 0xA0 // + A,B -> A+B
*EXPR 0xA0
POP_D
DAD_D
*
// 0xA1 // - A,B -> A-B
*EXPR 0xA1
POP_D
MOV_A,E
SUB_L
MOV_L,A
MOV_A,D
SBB_H
MOV_H,A
*
...
// 0xC0 // & A,B -> A&B
*EXPR 0xC0
POP_D
MOV_A,D
ANA_H
MOV_H,A
MOV_A,E
ANA_L
MOV_L,A
*
// 0xC1 // | A,B -> A|B
*EXPR 0xC1
POP_D
MOV_A,D
ORA_H
MOV_H,A
MOV_A,E
ORA_L
MOV_L,A
*
// 0xC2 // ^ A,B -> A^B
*EXPR 0xC2
POP_D
MOV_A,D
XRA_H
MOV_H,A
MOV_A,E
XRA_L
MOV_L,A
*
...
// 0xE0 // - A -> -A
*EXPR 0xE0
MOV_A,H
CMA
MOV_H,A
MOV_A,L
CMA
MOV_L,A
INX_H
*
// 0xE1 // ~ A -> ~A
*EXPR 0xE1
MOV_A,H
CMA
MOV_H,A
MOV_A,L
CMA
MOV_L,A
*
// 0xE2 // ! A -> !A
*EXPR 0xE2
#genlab %l1
MOV_A,H
ORA_L
JZ %l1
LXI_H, 1
%l1
DCX_H
*
// 0xF0 // ?: A,B,C -> A?B:C
*EXPR 0xF0
#genlab %l1
POP_D
POP_B
MOV_A,B
ORA_C
JZ %l1
XCHG
%l1
*
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
HL=-HL
Code: Select all
xor a
sub l
ld l,a
sbc a,a
sub h
ld h,a
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
см. второй пост с начала - Алоне похожим образом делал
тут правда хитрее, хоть и такое же количество тактов и байтов
откуда дровишки?
тут правда хитрее, хоть и такое же количество тактов и байтов
откуда дровишки?
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
часть кода z80 можно найти на ресурсах, посвященных с Texas Instruments.
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
Тут ещё такой момент - надо ли детектировать особые случаи при сдвигах? Типа если сдвиг 8 бит, то зачем бежать крутить биты если можно просто байт переставить? Другой момент, что на проверку и переход тоже время тратится, но оно всё таки будет меньше чем двигать побитно. Тоже самое с умножением - зачем двигать биты если один из множителей 0 или скажем 1? Ведь результат будет заведомо известен...
P.S. Сдвиги можно наверное как-то вот так сделать:Тут детектируется 2 особых случая - сдвиг на 0 ( см. RZ ) и сдвиг на 8 ( см. CPI 8 ). Кроме того сдвиг берётся по маске 31 - это чтобы сымитировать сишное поведение, когда сдвиг на 32 это тоже самое, что сдвиг на 0 (даже в случае 16-битных целых) - заодно устанавливаются флаги, чтобы быстро выскочить, если это был сдвиг на 0 (в этот момент в HL уже будет сидеть то, что при входе было в DE).
P.S. Сдвиги можно наверное как-то вот так сделать:
Code: Select all
\ SHIFT DE LEFT BY L&31 AND RETURN IN HL
SHIFTL: XCHG
MOV_A,E
ANI 31
RZ \ RETURN IF SHIFT BY 0
CPI 8
JNZ SHIFTL1
\ SPECIAL CASE - SHIFT BY 8
MOV_H,L
MVI_L, 0
RET
SHIFTL1:
DAD_H
DCR_A
JNZ SHIFTL1
RET
\ SHIFT DE RIGHT (ARITHMETICALLY) BY L&31 AND RETURN IN HL
SHIFTR: XCHG
MOV_A,E
ANI 31
RZ \ RETURN IF SHIFT BY 0
MOV_D,A
CPI 8
JZ SHIFTR3
MOV_A,H
RAL
JC SHIFTR2
SHIFTR0:
XRA_A
MOV_A,H
RAR
MOV_H,A
MOV_A,L
RAR
MOV_L,A
DCR_D
JNZ SHIFTR0
RET
SHIFTR1:
STC
SHIFTR2:
MOV_A,H
RAR
MOV_H,A
MOV_A,L
RAR
MOV_L,A
DCR_D
JNZ SHIFTR1
RET
SHIFTR3:
\ SPECIAL CASE - SHIFT BY 8
MOV_L,H
MOV_A,H
RAL
JC SHIFTR4
MVI_H, 0
RET
SHIFTR4:
MVI_H, #FF
RET
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
Идея интересная, но оптимизация заведет до абсурда - при сдвигах, кое количество кратно 8.
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
У меня 16-битные целые поэтому только сдвиг на 8 является часто встречающимся случаем, а сдвиг на 16 уже всё уведёт за пределы и я не думаю, что этот вариант надо ускорять...
Я тут за главного - если что шлите мыло на me собака shaos точка net
Re: [SDK] Новая математика для кросс-компилятора в 8080/z80
А не может такого быть, что используется var>>bitcount или явно var>>8 ?