МАРСОХОД

Open Source Hardware Project

Добро пожаловать, Гость
Логин: Пароль: Запомнить меня

ТЕМА: Минималистичное софт-ядро для Марсохода.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4842

  • Leka
  • Leka аватар Автор темы
  • Не в сети
  • Живу я здесь
  • Живу я здесь
  • Сообщений: 635
  • Спасибо получено: 54

Какие команды будут при эмуляции CALL и RET?

JMP - отложенный переход (в отличие от BR/BEQ/BNE/...), с задержкой в 1 такт, туда можно вставить команду пересылки из аккумулятора в регистр. В аккумуляторе будет адрес следующей команды. Поэтому для CALL:
JMP imm8[Rj] ;адрес подпрограммы в памяти по адресу imm8+(Rj)
ST Rr
Для RET:
JMP Rr
LD Rn ;или NOP

Будет ли указатель стека?

Аппаратного стека нет.

Нужен ли регистр константы 0?

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

Или любая константа будет в памяти?

В общем случае - да, в тч адреса подпрограмм и длинных переходов.


Имхо, сначала нужно проработать модель памяти, чтобы не мешало ограничение 8-разрядного смещения, и малое число регистров (8 ). Поэтому изучаю вывод symbolic. Для минималистичного ядра можно ввести ограничения на допустимые Си-конструкции, чтобы не усложнять компилятор.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Последнее редактирование: от Leka.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4843

  • Leka
  • Leka аватар Автор темы
  • Не в сети
  • Живу я здесь
  • Живу я здесь
  • Сообщений: 635
  • Спасибо получено: 54

alman пишет: Подскажите, как быть если архитектура не поддерживает 8 и 16 бит? На ассемблере эти разрядности я поддерживал с помощью различных приёмов (сдвиги и маски), оптимизировав непосредственно под каждую задачу. А вот как научить lcc эмулировать эти разрядности на архитектурах, которых их не поддерживают?

Советую изучить листинг с -target=symbolic, многое станет понятным.
Имхо, *.md просто описывает правила преобразования вывода с -target=symbolic в ассемблер.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4844

Подскажите, как быть если архитектура не поддерживает 8 и 16 бит? На ассемблере эти разрядности я поддерживал с помощью различных приёмов (сдвиги и маски), оптимизировав непосредственно под каждую задачу. А вот как научить lcc эмулировать эти разрядности на архитектурах, которых их не поддерживают?


Вопрос не понял.
В m16.md файле есть такие строки:
reg: CVII2(INDIRI1(addr)) "\tlb r%c,%0\n" 1
reg: CVUU2(INDIRU1(addr)) "\tlu r%c,%0\n" 1
reg: CVUI2(INDIRU1(addr)) "\tlu r%c,%0\n" 1
reg: CVII2(reg) "\tslli r%c,r%0,8\n\tsrai r%c,r%c,8\n" 2
reg: CVUI2(reg) "\tslli r%c,r%0,8\n\tsrli r%c,r%c,8\n" 2
reg: CVUU2(reg) "\tslli r%c,r%0,8\n\tsrli r%c,r%c,8\n" 2

Эти конструкции позволяют вести обмен между байтами памяти и 16-ти разрядными регистрами.

Николай.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4850

  • Leka
  • Leka аватар Автор темы
  • Не в сети
  • Живу я здесь
  • Живу я здесь
  • Сообщений: 635
  • Спасибо получено: 54
В систему команд внесены изменения.
Убраны отдельные команды безусловного и дальнего переходов, вместо них добавлены две команды беззнакового условного перехода LTU, GEU.
Безусловный переход эмулируется беззнаковым сравнением GEU с нулем (R0=0), дальний переход соответствует коду "запрещенной" команды "ST R0".
R0 всегда 0 при прямой адресации, при косвенной адресации R0 содержит указатель GP, который нельзя изменить командой ST R0.
EQ   src, imm  --  if(A == src) PC += imm8<<1   ;signed 
NE   src, imm  --  if(A != src) PC += imm8<<1   ;signed
LT   src, imm  --  if(A < src)  PC += imm8<<1   ;signed
GE   src, imm  --  if(A >= src) PC += imm8<<1   ;signed
GT   src, imm  --  if(A > src)  PC += imm8<<1   ;signed
LE   src, imm  --  if(A <= src) PC += imm8<<1   ;signed
LTU  src, imm  --  if(A < src)  PC += imm8<<1   ;unsigned 
GEU  src, imm  --  if(A >= src) PC += imm8<<1   ;unsigned 
LD   src       --  A = src
ST   dst       --  dst = A
ADD  src       --  A += src
SUB  src       --  A -= src
AND  src       --  A &= src
OR   src       --  A |= src
XOR  src       --  A ^= src
ROT  src       --  A = rot(A, src[3:0])  ;эмуляция LSH, RSH

ADD   0        --  A += 0                ;эмуляция NOP
GEU   0        --  PC += imm8<<1         ;эмуляция безусловного перехода
ST    0        --  A = PC, PC = ALU      ;эмуляция дальних переходов JMP, CALL, RET
Источник src=R0 всегда подразумевает константу 0.
Переходы всегда на четный адрес, для выравнивания используется NOP.

Программная модель памяти минималистичного ядра.
Принята в предположении, что в практических программах основной объем памяти расходуется на код и массивы, но не на одиночные константы, аргументы, переменные и указатели.
imm8(GP) подразумевает адресацию одиночных глобальных констант, функций, переменных, указателей.
imm8+FP(GP) подразумевает адресацию аргументов функций.
imm8+LP(GP) подразумевает адресацию одиночных локальных перменных, указателей, LP=FP+FSIZE.
imm8+LP+LSIZE(GP) подразумевает адрес возврата, если необходим. Функции нерекурсивные.
Если GSIZE не превышает 512 байт, то в качестве GP используется только R0.
Cверх 512 байт в качестве GP используется R1=R0+512, сверх 1024 байт - R2=R1+512, и тд.
Все эти адреса лежат внутри сегмента GSIZE, массивы в общем случае распределяются вне этого сегмента.
Для адресации массивов в общем случае используется imm8(Rn), Rn != GP, n<8.
Регистры R0..R7 лежат в памяти, начиная с абсолютного адреса 0.

Пример:
int out;
void outstr(char *s){ while(out=*s)s++; }
void main(){ outstr("Hello, world!"); }
GSIZE=12байт (+ на системные нужды):
2 переменная out
2 адрес функции outstr()
2 аргумент *s
2 адрес возврата из outstr()
2 адрес функции main()
2 указатель на строку "Hello, world!"

Ассемблер, переделан из вывода -target=symbolic:
outstr:
    geu 0, L3  ;безусловный переход на L3:
L2:
    ld  s(0)
    add _1(0)  ;s+=1 
    st  s(0)
L3:
    ld  s(0)  ;загружаем адрес текущего символа
    st  loadchar+4(0) ;пишем в аргумент функции
    ld  loadchar(0) ;загружаем адрес функции  
    st  0 ;переход на функцию loadchar()
    ld  loadchar+2(0) ;загружаем результат функции
    st  out(0)
    bne 0, L2  ;условный переход на L2: 
    ld  outstr+4(0)  ;загружаем адрес возврата
    st  0  ;возврат из outstr	
main:
    ld  "Hello, world!\000"(0)  ;загружаем указатель на строку
    st  outstr+2(0)  ;аргумент outstr()  
    ld  outstr(0)  ;адрес outstr()
    st  0  ;переход
    ...

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Последнее редактирование: от Leka.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4851

  • Leka
  • Leka аватар Автор темы
  • Не в сети
  • Живу я здесь
  • Живу я здесь
  • Сообщений: 635
  • Спасибо получено: 54
Думаю, регистры нужно оставить только на системные нужды, и ассемблерные библиотечные функции.
Не думаю, что в *.md легко будет описать чисто аккумуляторную архитектуру с рабочими регистрами. А без этого многочисленные копирования аккумулятор <--> регистр сведут на нет всю выгоду от использования рабочих регистров, и лучше будет сразу пересылать аккумулятор <--> память.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4852

Можно для отладки ввести следующий ключ, который выводит строки исходников.

..\bin\lcc.exe -Wf-g1,; -Wf-target=symbolic -S tstm16.c

Николай.

P.S.
А что означает подчеркивание _1 в этой строке?
add _1(0) ;s+=1
Спасибо сказали: Leka

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Последнее редактирование: от Ynicky.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4853

  • Leka
  • Leka аватар Автор темы
  • Не в сети
  • Живу я здесь
  • Живу я здесь
  • Сообщений: 635
  • Спасибо получено: 54
Константы в памяти. _1, это адрес константы относительно GP.
Вся адресация - только словами, @(imm8<<1+Rn). Младший бит Rn предполагается использовать для программного доступа к байтам.

Кстати, ассемблер st16 свой, или стандартный/переделанный из стандартного ?

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Последнее редактирование: от Leka.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4854

Кстати, ассемблер st16 свой, или стандартный/переделанный из стандартного ?


За основу взял исходники от xr16.

Николай.

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4862

  • Leka
  • Leka аватар Автор темы
  • Не в сети
  • Живу я здесь
  • Живу я здесь
  • Сообщений: 635
  • Спасибо получено: 54

Ynicky пишет: Можно для отладки ввести следующий ключ, который выводит строки исходников.
..\bin\lcc.exe -Wf-g1,; -Wf-target=symbolic -S tstm16.c

Жаль, что так только для symbolic получается, хотел еще для других target посмотреть...

Решил отказаться от чисто аккумуляторной архитектуры, и сделать другую, для которой проще будет настроить LCC, и получить приемлемое быстродействие . Заодно расширить шину команд до 16 разрядов. На числе ЛЕ это не скажется (планирую уложиться в ~200 ЛЕ). Думаю, еще много изменений будут, выкладывать краткие описания промежуточных вариантов?

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Минималистичное софт-ядро для Марсохода. 3 года 10 мес. назад #4863

Этот ключ -Wf-g1,; у меня не работает только в моем процессоре st16.
Так как на его основе сделан файл m16.md, то и на нем это тоже отражается.
Чтобы исправить эту ситуацию, нужно закоментировать следующую строку:

static void defsymbol(Symbol p) {
char *cfile;
int iI;
iI = strlen(file)-2;
cfile = file;
/// cfile[iI] = '_';

if (p->scope >= LOCAL && p->sclass == STATIC)
p->x.name = stringf("_%s_%d", cfile, genlabel(1));
else if (p->generated)
p->x.name = stringf("_%s_%s", cfile, p->name);
else if (p->scope == GLOBAL || p->sclass == EXTERN)
p->x.name = stringf("_%s", p->name);
else
assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
p->x.name = p->name;
}

Так как у меня в ассемблере на st16 нет линковщика, я склеиваю несколько
ассемблерных файлов в один и уже потом ассемблирую. Чтобы в разных файлах
были разные метки, я в них добавляю название файла и заменяю точку на
подчеркивание. Но это почему-то убирает строки исходника.
Если вы с Alman разберетесь, было бы очень хорошо (Я не программист по
образованию).

Что касается промежуточных результатов, то мне было-бы интересно.

Николай.
Спасибо сказали: Leka

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

Время создания страницы: 0.233 секунд

ВКонтакте  facebook  GitHub  YouTube  Twitter
Вы здесь: Начало Forum Наш форум Проекты пользователей Минималистичное софт-ядро для Марсохода.