Здравствуйте, друзья.
Задумался я тут об эффективном (по скорости) решении следующей задачи: выполнить переход на одну из нескольких веток программы в зависимости от значения параметра A.
Например, одно из возможных решений выглядит так:
Данное решение канонично и универсально, но имеет 2 недостатка. 1) Скорость - 64 такта; 2) используется две регистровые пары.Код:LD HL,JUMP_TBL ;10 ADD A,A ;4 LD C,A ;4 LD B,0 ;7 ADD HL,BC ;11 LD A,(HL) ;7 INC HL ;6 LD H,(HL) ;7 LD L,A ;4 JP (HL) ;4 JUMP_TBL: DW ROUTINE1 DW ROUTINE2 DW ROUTINE3 ....
Улучшенный вариант:
Здесь переход происходит за 62 такта и используется только одна регистровая пара.Код:LD HL,JUMP_TBL ;10 ADD A,A ;4 ADD A,L ;4 LD L,A ;4 ADC A,H ;4 SUB L ;4 LD H,A ;4 LD A,(HL) ;7 INC HL ;6 LD H,(HL) ;7 LD L,A ;4 JP (HL) ;4 JUMP_TBL: DW ROUTINE1 DW ROUTINE2 DW ROUTINE3 ....
Если гарантировать размещение таблицы без пересечения границы 256-байтных страниц, то можно еще сэкономить:
Исполняется за 48 тактов.Код:LD HL,JUMP_TBL ;10 ADD A,A ;4 ADD A,L ;4 LD L,A ;4 LD A,(HL) ;7 INC L ;4 LD H,(HL) ;7 LD L,A ;4 JP (HL) ;4 JUMP_TBL: DW ROUTINE1 DW ROUTINE2 DW ROUTINE3 ....
Если размещать таблицу в начале 256-байтной страницы - то:
Этот вариант исполняется за 41 такт.Код:LD H, HIGH(JUMP_TBL) ;7 ADD A,A ;4 LD L,A ;4 LD A,(HL) ;7 INC L ;4 LD H,(HL) ;7 LD L,A ;4 JP (HL) ;4 .ALIGN 256 JUMP_TBL: DW ROUTINE1 DW ROUTINE2 DW ROUTINE3 ....
Если все ветки, на которые производится переход, находятся в той же 256-байтной странице, что и таблица, то можно еще сэкономить:
Данный вариант я уже не могу улучшить, он исполняется за 22 такта. По-прежнему остается проблема использования HL, в которой можно было бы передавать параметры, если бы эта пара не использовалась для перехода. Ну и серьёзные ограничения по размещению кода.Код:LD H, HIGH(JUMP_TBL) ;7 LD L,A ;4 LD L,(HL) ;7 JP (HL) ;4 .ALIGN 256 JUMP_TBL: DB LOW(ROUTINE1) DB LOW(ROUTINE2) DB LOW(ROUTINE3) ....
Без использования HL задачу можно решить, например, так:
Исполняется за 41 такт. Достоинства: не используется HL. Недостатки: нельзя размещать в ПЗУ; дистанция перехода ограничена.Код:ADD A,A ;4 LD (JT+1),A ;13 JT: JR JUMP_TBL ;12 JUMP_TBL: JR ROUTINE1 ;12 JR ROUTINE2 ;12 JR ROUTINE3 ;12 ....
При малом количестве веток можно еще рассмотреть такой вариант:
Тут полная свобода по размещению кода; исполняется за 16 тактов в лучшем случае, а в худшем - за (N-1)*11+16, где N - количество веток. Можно размещать в ПЗУ по произвольным адресам, но дистанция перехода ограничена.Код:OR A ;4 JR Z,ROUTINE1 ;7/12 DEC A ;4 JR Z,ROUTINE2 ;7/12 DEC A ;4 JR Z,ROUTINE3 ;7/12 ....
Интересуют в первую очередь решения, где подпрограмм мало (4-8шт), и они короткие (ограниченность дистанции перехода не играет роли). Может быть, у кого-нибудь возникнут идеи получше?


Ответить с цитированием
Размещение рекламы на форуме способствует его дальнейшему развитию 

