Перейти к содержанию
    

На этой неделе постараюсь выложить первую версию компилятора. Отвлекают вопросы методического характера, например: Си ориентирован на явное использование указателей --> получается неудобно для архитектуры с большим регистровым файлом, тк указатели нельзя применять к регистрам...

 

 

Память программ и регистровый файл

Нужна еще память данных для массивов, косвенно адресуемых LOAD/STORE.

Изменено пользователем Leka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужна еще память данных для массивов, косвенно адресуемых LOAD/STORE.

На днях сделаю.

 

 

Спасибо конечно, но вот те кто не пользуются альедеком должны вытаскивать структуру из скомпилированного bdf файла? Это я к тому что структурная и функциональная схема не помешали бы, также как и описание портов ввода/вывода процессора %)

Учту.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтобы проще было вылавливать ошибки в компиляторе с "ассемблерного" подмножества Си, решил добавить промежуточный уровень "машинного" подмножества Си:

... --> "ассемблерный" Си --> "машинный" Си --> машинные коды.

 

Пример: N-ферзей на "машинном" Си для 3х-операндной архитектуры без типов,

main() - тестовая программа на Си - игноируется компилятором в машинные коды по пробелу в начале строки.

R1;
R2;
R3[20];
R4[20];
R5[20];
R6[20];
R7;
R8;
R9;
R10;
R11;
R12;
R13;
R14;
	queens(){
L1:R2=0;
L2:R12=R1&1;
L3:R13=1<<R1;
L4:R9=R13-1;
L5:R13=R1>>1;
L6:R7=R9>>R13;
L7:R3[1]=0;
L8:R4[1]=0;
L9:R5[1]=0;
L10:R6[1]=R7;
L11:R10=1;
L12:if(R7==0)goto L46; 
L13:R13=0-R7;
L14:R8=R7&R13;
L15:R13=-1-R8;
L16:R7=R7&R13;
L17:if(R10!=R12)goto L20; 
L18:if(R7!=0)goto L20;
L19:R2=R2<<1;
L20:if(R10==R1)goto L44;
L21:R11=R10+1;
L22:R6[R10]=R7;
L23:R13=R3[R10];
L24:R13=R13|R8;
L25:R3[R11]=R13;
L26:R13=R4[R10];
L27:R13=R13|R8;
L28:R13=R13<<1;
L29:R4[R11]=R13;
L30:R13=R5[R10];
L31:R13=R13|R8;
L32:R13=R13>>1;
L33:R5[R11]=R13;
L34:R13=R3[R11];
L35:R14=R4[R11];
L36:R13=R13|R14;
L37:R14=R5[R11];
L38:R13=R13|R14;
L39:R13=-1-R13;
L40:R13=R13&R9;
L41:R7=R13;
L42:R10=R11;
L43:goto L45;
L44:R2=R2+1;
L45:goto L48;
L46:R10=R10-1;
L47:R7=R6[R10];
L48:if(R10!=0)goto L12;
L49:if(R12!=0)goto L51;
L50:R2=R2<<1;
L51:return(R2);
	}
	main(){
		int n,cnt;
		for(n = 1; n < 15; n = n + 1){
			R1= n;
			queens();
			cnt = R2;
			printf("queens(%d)=%d \n", n, cnt);
		}		
	}

Изменено пользователем Omen_13
Оформление кода

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Косвенную адресацию памяти

R6[R10]=R7; --> STORE R7,(R6+R10)

R13=R3[R10]; --> LOAD R13,(R3+R10)

Для 2х-операндной архитектуры:

R6[R10]=R7; -->

MOV R0,R6

ADD R0,R10

ST R7,(R0)

R13=R3[R10]; -->

MOV R0,R3

ADD R0,R10

LD R13,(R0)

или переписать "ассемблерный" код под 2х-операндную архитектуру с использованием указателей R6 R3 вместо пар база-индекс:

*R6=R7;

R13=*R3;

и учесть такие мнемоники в трансляторе в машинные коды.

 

 

 

Вариант N-ферзей с указателями на "ассемблерном" Си (кроме main(){}).

queens( int N ){
int
count,
arow[20], 
aleft[20], 
aright[20], 
aposs[20],
poss, 
place, 
val, 
pos, 
pos1, 
N1,
temp,	
temp1,
*prow, 
*pleft, 
*pright, 
*pposs,
*prow1, 
*pleft1, 
*pright1, 
*pposs1;

count = 0;	
N1= N & 1;
temp = 1 << N;
val = temp - 1;
temp = N >> 1;
poss = val >> temp;
pos = 1;	
//
prow=arow+1;
pleft=aleft+1;
pright=aright+1;
pposs=aposs+1;
//arow[1] = 0;
//aleft[1] = 0;
//aright[1] = 0;
//aposs[1] = poss;	
*prow = 0;
*pleft = 0;
*pright = 0;
*pposs = poss;
do{
	if( poss != 0 ){
		temp = -poss;
		place = poss & temp;
		temp = ~place;
		poss = poss & temp;
		if( pos == N1 && poss == 0 )  
			count = count << 1;
		if( pos != N ){
			pos1 = pos + 1;
			//
			prow1 = prow+1;
			pleft1 = pleft+1;
			pright1 = pright+1;
			pposs1 = pposs+1;			  
			//aposs[pos] = poss;	 
			*pposs = poss;	 
			//temp = arow[pos];
			temp = *prow;
			temp = temp | place;
			//arow[pos1] = temp;
			*prow1 = temp;
			//temp = aleft[pos];
			temp = *pleft;
			temp = temp | place;
			temp = temp << 1;
			//aleft[pos1] = temp;  
			*pleft1 = temp;  
			//temp = aright[pos];	
			temp = *pright;	
			temp = temp | place;	
			temp = temp >> 1;	
			//aright[pos1] = temp;
			*pright1 = temp;
			//temp = arow[pos1];	
			temp = *prow1;	
			//temp1 = aleft[pos1];
			temp1 = *pleft1;
			temp = temp | temp1;
			//temp1 = aright[pos1];
			temp1 = *pright1;
			temp = temp | temp1;
			temp = ~temp;				
			temp = temp & val;
			poss = temp;
			pos = pos1;
			//
			prow += 1;
			pleft += 1;
			pright += 1;
			pposs += 1;	
		}else
			count = count + 1;
	}else{ 
		pos = pos - 1;
		//
		prow -= 1;
		pleft -= 1;
		pright -= 1;
		pposs -= 1;
		//poss = aposs[pos]; 
		poss = *pposs; 
	}
}while( pos != 0 );	
if( N1 == 0 )
	count = count << 1;
return count;
}

main(){
int N;
for(N = 1; N < 15; N = N + 1){
	printf("queens(%d)=%d \n", N, queens(N)); 
}
}

Изменено пользователем Omen_13
Оформление кода

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Закончил "в черне" процессор.

Вынес память программ и данных из ядра.

Дополнил системной шиной AMBA AHB и отладочными блоками для

работы через JTAG.

Теперь только тесты, тесты, правка и еще раз тесты.

Описание дополню в выходные.

 

Николай.

rf32.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Написал компилятор "ассемблерный" Си --> "машинный" Си, причешу - выложу (либо завтра, если успею, либо в понедельник).

Надо-бы побольше программ на "ассемблерном" Си для тестирования (как компилятора, так и процессора).

 

"Машинный" Си --> машинные коды на этой неделе уже не успею, но эта задачка заметно проще.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Первая версия компилятора "ассемблерный" Си --> "машинный" Си.

Поддерживаются: int, if-else, do-while, блоки { }, см. примеры N-ферзей.

В текущей версии не поддерживаются вложенные круглые скобки и круглые скобки в выражениях.

 

Запуск из командной строки:

a2m < входной_файл > входной_файл

 

Например(см. a.bat):

a2m < q3.c > q3..c

 

Выходные (и входные) файлы можно проверить любым Си-компилятором, например, Tiny C Compiler в скриптовом режиме:

c:\tcc\tcc.exe -run q3..c

 

При установленном TinyCC:

a q3

 

 

Под "ассемблерным" подмножеством Си подразумевается отсутствие длинных арифметических и логических выражений, допускаются только 3х-операндные выражения(с учетом адреса перехода), которые м/б непосредственно преобразованы в машинные коды.

 

По поводу FP(указателя на кадр) - как в подпрограммах получать доступ к глобальным переменным в регистровом файле?

C.1.0.0.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня указатель на область локальных переменных аппаратно "разворачивал" нумерацию регистров, так что R(0), R(1), R(2), ... в подпрограмме любой вложенности указывали на глобальные переменные, а R(-1), R(-2), R(-3) - на локальные, или наоборот. Например, для 8 регистров:

 R0  R1  R2  R3  R4  R5  R6  R7  -  int R0; 
R0  R7  R6  R5  R4  R3  R2  R1  -  main(){ int R7, R6, R5; f1( R5 ); }
R0  R1  R2  R7  R6  R5  R4  R3  -  f1( int R7 ){ int R6, R5; f2( R5 ); }
R0  R1  R2  R3  R4  R7  R6  R5  -  f2( int R7 ){ int R6, R5; ... }

С программной точки зрения подобная перенумерация регистров очень удобна. Проверил и в железе, и в ассемблере. Единственный недостаток - лишняя ступень логики.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как в подпрограммах получать доступ к глобальным переменным в регистровом файле?

Тут я не понял. Я всегда считал, что глобальные переменные находятся в памяти данных.

И доступ к ним осуществляется через load/store.

Если они будут находиться в регистровом файле, тогда без переключения регистров не обойтись.

И сколько их может потребоваться?

 

Николай.

 

P.S.

Предлагаю пока не заморачиваться по поводу FP.

А дальше будет видно.

Изменено пользователем Ynicky

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для вспомогательной подпрограммы основные данные - внешние, "в противном случае зовется ... иначе" - задача. Локальных по своей сути данных немного, это промежуточные результаты выражений, счетчики циклов, и тп.

Нет никакого смысла делать большой регистровый файл для локальных данных: 16 уровней вложенности пп * 4 локальные переменные в среднем = 64 регистра.

Если основные данные не в регистровом файле, имеет смысл отказаться от load/store архитектуры, добавив косвенно-регистровую адресацию ( *a=*b+*c; if(*a==*d)...; и тп ). Была у меня такая в железе, см ветку "посоветуйте простой софт-процессор".

 

Предлагаю пока не заморачиваться по поводу FP.

Согласен, сначала нужен компилятор "машинный" Си --> машинные коды.

Изменено пользователем Leka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

To Leka:

Попробовал написать простенький тест.

После компиляции a2m запустил LCC.

Пока 2 явных замечания:

1. return надо отделить от 1 и 0.

2. в разных подпрограммах повторяющиеся метки.

Проект во вложении.

 

Николай.

tst_jcc.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. return надо отделить от 1 и 0.

Забыл написать, надо "return(1);" вместо "return 1;" Сделано специально - как вызов функции, а не ключевое слово.

2. в разных подпрограммах повторяющиеся метки.

Вроде это не противоречит стандарту (локальность меток в пределах функции), но если надо - могу добавлять имя функции к метке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В a2m пока только один тип "int", поэтому "void" не допускается.

Ошибки потом поправлю, сейчас прорабатываю компилятор в машинные коды.

Из-за зависимости длины инструкции от данных (вставка imm20 и тп), решил поменять концепцию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...