SDCC - Small Device C Compiler
В компилятор SDCC (начиная с ревизии #6588), добавлен новый регистровый оптимизатор, который генерит более компактный код z80.
По заявлянию автора нового оптимизатора Philipp Klaus Krause, в теперешнем виде, этот оптимизатор уже сравнялся по размеру генерируемого кода, с компилером HITECH-C 7.80PL2
(Также уже запланированы всячиские новые улучшения для оптимизатора.)
Сам оптимизатор был запланирован уже давно.
SDCC - Small Device C Compiler
В SDCC теперь есть поддержка работы с Си данными, в разных банках памяти. Реализовано это через стандартный Embedded C механизм "Named address spaces".
Пример:
void set_bank0(void); // функция включения банка 0
void set_bank1(void); // функция включения банка 1
__addressmod set_bank0 space_bank0; // "Именованное адресное пространство" space_bank0, которое использует ф-цию set_bank0
__addressmod set_bank1 space_bank1; // "Именованное адресное пространство" space_bank1, которое использует ф-цию set_bank1
space_bank0 int x; // int в адресном пространстве space_bank0
space_bank1 int* y; // указатель на int в адресном пространстве space_bank1
space_bank0 int *space_bank1 z; // указатель в адресном пространстве space_bank1, который указывает на на int, в адресном пространстве space_bank0
Суть метода:
SDCC автоматически вызывает необходимую функцию при доступе (чтение или запись) к переменной. (Функция должна подключить нужную банку в адресное пространство CPU. )
Manual.
Ветка обсуждения из sdcc-user mail list (есть пример кода).
SDCC и подпрограммы на асме
Цитата:
Сообщение от
Eltaron
попутно вспомнил, чем еще раздражает sdcc - решетками # перед числами в асме. Мозг отказывается воспринимать такие числа не как hex
Цитата:
Сообщение от
Valen
Да, есть такая бяка.
Поэтому использую sdcc asm, только для маленьких inline кусочков асм кода.
Если нужно кодить на асме много, просто юзаю другой асм компилятор (с более удобным синтаксисом) и затем уже линкую скомпиленный асмом бинарь к бинарю sdcc.
Цитата:
Сообщение от
Eltaron
а как, руками? там форматы все какие-то самописные и ни с чем не совместимые вроде бы
Цитата:
Сообщение от
Valen
Да, руками бинарники объединяю.
(например, вызываю bin2c для асмовского бинарника и потом просто #include в sdcc Си файл или же загружаю файл асмовского бинарника, при старте программы)
Цитата:
Сообщение от
Eltaron
Вариант, но ведь так теряется вся полезная инфа - положение глобальных переменных, имена, адреса функций...
Да, получается так.
пример кодогенерации SDCC 3.1.2
Примерчик, чтобы был.
Ситуация:
В видео-памяти лежит 15 фонтов, размером 8x8 (1байт на пиксел). Фонты занимают 12 страниц видео памяти (0-11).
(Любую страницу видео-памяти, можно подключить в 8KB адресное окно z80 и затем уже в этом окне, z80 может работать с видео-памятью.)
Нужно:
Пройтись по этим фонтам и присвоить не-нулевым пикселям нужный цвет. Цвет для каждого фонта разный, рассчитывается по ходу дела.
Заметка:
4 байта локальных переменных легло на регистры z80.
Остальные переменные объявлены как static, что ускорит обращение к ним через константный адрес, а не через стэк и ix (например ld a,(ix+1) )
Код:
#define FONT_8x8_SIZE (96UL*8*8) // chunky font size
void Display_SetFontPixelColors(void)
{
BYTE* pFont = (BYTE*)VIDEO_BASE;
WORD counter = 0;
static BYTE fontColor = 1;
static BYTE video_page = 0;
PAGE_IN_VIDEO_RAM();
SET_VIDEO_PAGE(video_page);
while(video_page < 12) {
// modify pixel
if(*pFont)
*pFont = fontColor; // if pixel is not zero, set pixel to font color
pFont++;
if(pFont >= (BYTE*)VIDEO_BASE + 0x2000) {
pFont = (BYTE*)VIDEO_BASE;
video_page++; // inc video page
SET_VIDEO_PAGE(video_page);
}
counter++;
if(counter >= (WORD)FONT_8x8_SIZE) {
counter = 0;
fontColor++; // inc font color
}
}
PAGE_OUT_VIDEO_RAM();
}
Код:
; ---------------------------------
; Function Display_SetFontPixelColors
; ---------------------------------
_Display_SetFontPixelColors_start::
_Display_SetFontPixelColors:
;src/fs/display_tilemap.c:409: BYTE* pFont = (BYTE*)VIDEO_BASE;
ld de,#0x2000
;src/fs/display_tilemap.c:410: WORD counter = 0;
ld bc,#0x0000
;src/fs/display_tilemap.c:416: PAGE_IN_VIDEO_RAM();
in a,(_io__sys_mem_select)
set 6, a
out (_io__sys_mem_select),a
;src/fs/display_tilemap.c:417: SET_VIDEO_PAGE(video_page);
ld a,(#_Display_SetFontPixelColors_video_page_1_122 + 0)
;src/fs/display_tilemap.c:419: while(video_page < 12) {
ld (#_mm__vreg_vidpage + 0),a
00107$:
ld iy,#_Display_SetFontPixelColors_video_page_1_122
ld a,0 (iy)
sub a, #0x0C
jr NC,00109$
;src/fs/display_tilemap.c:421: if(*pFont)
ld a,(de)
or a, a
jr Z,00102$
;src/fs/display_tilemap.c:422: *pFont = fontColor; // if pixel is not zero, set pixel to font color
ld a,(#_Display_SetFontPixelColors_fontColor_1_122 + 0)
ld (de),a
00102$:
;src/fs/display_tilemap.c:423: pFont++;
inc de
;src/fs/display_tilemap.c:424: if(pFont >= (BYTE*)VIDEO_BASE + 0x2000) {
ld a,d
sub a, #0x40
jr C,00104$
;src/fs/display_tilemap.c:425: pFont = (BYTE*)VIDEO_BASE;
ld de,#0x2000
;src/fs/display_tilemap.c:426: video_page++; // inc video page
ld iy,#_Display_SetFontPixelColors_video_page_1_122
inc 0 (iy)
;src/fs/display_tilemap.c:427: SET_VIDEO_PAGE(video_page);
ld a,0 (iy)
ld iy,#_mm__vreg_vidpage
ld 0 (iy),a
00104$:
;src/fs/display_tilemap.c:430: counter++;
inc bc
;src/fs/display_tilemap.c:431: if(counter >= (WORD)FONT_8x8_SIZE) {
ld a,b
sub a, #0x18
jr C,00107$
;src/fs/display_tilemap.c:432: counter = 0;
ld bc,#0x0000
;src/fs/display_tilemap.c:433: fontColor++; // inc font color
ld iy,#_Display_SetFontPixelColors_fontColor_1_122
inc 0 (iy)
jr 00107$
00109$:
;src/fs/display_tilemap.c:438: PAGE_OUT_VIDEO_RAM();
in a,(_io__sys_mem_select)
and a, #0xBF
out (_io__sys_mem_select),a
ret
_Display_SetFontPixelColors_end::