diff --git a/Compiler b/Compiler index bae1649..7b16544 100644 Binary files a/Compiler and b/Compiler differ diff --git a/Compiler.exe b/Compiler.exe index ed60a5b..b5fcf29 100644 Binary files a/Compiler.exe and b/Compiler.exe differ diff --git a/doc/MSP430.txt b/doc/MSP430.txt index d5ba2db..053401a 100644 --- a/doc/MSP430.txt +++ b/doc/MSP430.txt @@ -232,8 +232,7 @@ Oberon-реализациях выполнение такой операции R14: указатель кучи, используется в стандартной процедуре NEW, а также для контроля переполнения стэка - R15: используется при обработке прерываний перед вызовом - пользовательского обработчика + R15: используется при обработке прерываний ------------------------------------------------------------------------------ Вызов процедур и кадр стэка @@ -346,13 +345,14 @@ SYSTEM. PUSH #30 ; поместить в стэк приоритет прерывания Label: - MOV SP, R15 ; настроить R15 на структуру данных прерывания (см. далее) PUSH R4 ; сохранить рабочие регистры (R4 - R7) ... PUSH R7 - PUSH R15 ; передать параметр interrupt в обработчик (см. далее) - PUSH @R15 ; передать параметр priority в обработчик (см. далее) - CALL int ; вызвать обработчик (см. далее) + MOV SP, R4 ; настроить R4 на структуру данных прерывания (см. далее) + ADD #8, R4 + PUSH R4 ; передать параметр interrupt в обработчик (см. далее) + PUSH @R4 ; передать параметр priority в обработчик (см. далее) + CALL @R15 ; вызвать обработчик (см. далее) ADD #4, SP ; удалить из стэка параметры обработчика POP R7 ; восстановить рабочие регистры (R7 - R4) ... @@ -394,10 +394,9 @@ SYSTEM. Инициализация и финализация программы В начало программы компилятор вставляет код, который: - - инициализирует регистры SP и R14 + - инициализирует регистры SP, R14 и R15 - выключает сторожевой таймер - - назначает пустой обработчик прерываний - - сбрасывает обработчик ошибок + - назначает пустой обработчик прерываний и пустой обработчик ошибок В конец программы добавляет команду BIS #16, SR; выключить CPU @@ -405,15 +404,15 @@ SYSTEM. ------------------------------------------------------------------------------ Структура ОЗУ (RAM) - начало -> | спец. переменные | глобальные переменные | куча/стэк | <- конец + начало -> | куча/стэк | спец. переменные | глобальные переменные | <- конец - Компилятор поддерживает размер ОЗУ 128..2048 байт. В нижних адресах -располагаются специальные переменные, и далее пользовательские глобальные + Компилятор поддерживает размер ОЗУ 128..2048 байт. В верхних адресах +располагаются пользовательские глобальные переменные и скрытые специальные переменные. Оставшаяся часть памяти отводится для кучи и стэка (не менее 40 байт, минимально необходимо для обработки прерываний и ошибок). При старте программы, в регистр R14 записывается адрес начала области кучи/стэка, а -регистр SP настраивается на конец ОЗУ (начало_ОЗУ + размер_ОЗУ). При выделении -памяти процедурой NEW, значение регистра R14 увеличивается (если есть +регистр SP настраивается на конец этой области (адрес спец. переменных). При +выделении памяти процедурой NEW, значение регистра R14 увеличивается (если есть свободная память). Таким образом, стэк и куча растут навстречу друг другу. Проверка переполнения стэка производится только при входе в процедуру, если эта проверка не отключена при компиляции (-nochk s). diff --git a/lib/MSP430/MSP430.ob07 b/lib/MSP430/MSP430.ob07 index 6e35d2a..fc5696c 100644 --- a/lib/MSP430/MSP430.ob07 +++ b/lib/MSP430/MSP430.ob07 @@ -23,18 +23,15 @@ CONST bits_offs = bits - 32; types = bits_offs - 2; - ram = 200H; - - trap = ram; - int = trap + 2; - - GIE* = {3}; CPUOFF* = {4}; OSCOFF* = {5}; SCG0* = {6}; SCG1* = {7}; + int_offs = 0; + trap_offs = 2; + TYPE @@ -46,17 +43,29 @@ TYPE PROCEDURE SetTrapProc* (TrapProc: TTrapProc); +VAR + ptr: INTEGER; + BEGIN - SYSTEM.PUT(trap, TrapProc) + SYSTEM.GET(sp, ptr); + IF TrapProc = NIL THEN + SYSTEM.PUT(ptr + trap_offs, empty_proc) + ELSE + SYSTEM.PUT(ptr + trap_offs, TrapProc) + END END SetTrapProc; PROCEDURE SetIntProc* (IntProc: TIntProc); +VAR + ptr: INTEGER; + BEGIN - IF IntProc # NIL THEN - SYSTEM.PUT(int, IntProc) + SYSTEM.GET(sp, ptr); + IF IntProc = NIL THEN + SYSTEM.PUT(ptr + int_offs, empty_proc) ELSE - SYSTEM.PUT(int, empty_proc) + SYSTEM.PUT(ptr + int_offs, IntProc) END END SetIntProc; diff --git a/source/Compiler.ob07 b/source/Compiler.ob07 index 1359430..d486444 100644 --- a/source/Compiler.ob07 +++ b/source/Compiler.ob07 @@ -192,7 +192,7 @@ BEGIN C.Ln; C.String("Akron Oberon Compiler v"); C.Int(UTILS.vMajor); C.String("."); C.Int2(UTILS.vMinor); - C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit) 2021-01-16"); + C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit) 2021-01-17"); C.StringLn("Copyright (c) 2018-2021, Anton Krotov"); IF inname = "" THEN diff --git a/source/MSP430.ob07 b/source/MSP430.ob07 index 8edc266..306b3ab 100644 --- a/source/MSP430.ob07 +++ b/source/MSP430.ob07 @@ -1577,12 +1577,12 @@ BEGIN END translate; -PROCEDURE prolog (ramSize: INTEGER); +PROCEDURE prolog; VAR i: INTEGER; BEGIN - RTL.Init(EmitLabel, EmitWord, EmitCall, ramSize); + RTL.Init(EmitLabel, EmitWord, EmitCall); FOR i := 0 TO LEN(RTL.rtl) - 1 DO RTL.Set(i, NewLabel()) END; @@ -1593,15 +1593,16 @@ BEGIN EmitWord(0); Op2(opMOV, incr(PC), HP); EmitWord(0); + MovRR(SP, IR); Op2(opMOV, imm(5A80H), dst_x(0120H, SR)); (* stop WDT *) - Op2(opMOV, imm(RTL.empty_proc), dst_x(RTL.int, SR)); - Op2(opMOV, imm(0), dst_x(RTL.trap, SR)) + Op2(opMOV, imm(RTL.empty_proc), dst_x(0, SP)); + Op2(opMOV, imm(RTL.empty_proc), dst_x(2, SP)); END prolog; PROCEDURE epilog; VAR - L1, i: INTEGER; + L1, i, n: INTEGER; BEGIN Op2(opBIS, imm(10H), SR); (* CPUOFF *) @@ -1618,18 +1619,20 @@ BEGIN EmitLabel(L1); - MovRR(SP, IR); - + n := 0; FOR i := 0 TO 15 DO IF i IN R.regs + R.vregs THEN - Push(i) + Push(i); + INC(n) END END; - Push(IR); - Op1(opPUSH, IR, sINDIR); - Op1(opCALL, SR, sIDX); - EmitWord(RTL.int); + MovRR(SP, R4); + Op2(opADD, imm(n * 2), R4); + + Push(R4); + Op1(opPUSH, R4, sINDIR); + Op1(opCALL, IR, sINDIR); Op2(opADD, imm(4), SP); FOR i := 15 TO 0 BY -1 DO @@ -1686,7 +1689,7 @@ BEGIN RelList := LISTS.create(NIL); REG.Init(R, Push, Pop, mov, xchg, NIL, NIL, {R4, R5, R6, R7}, {}); - prolog(ram); + prolog; translate(chkSTK IN options.checking); epilog; @@ -1701,10 +1704,12 @@ BEGIN ERRORS.Error(203) END; - Bss.address := RTL.ram + RTL.VarSize; - Bss.size := IL.codes.bss + IL.codes.bss MOD 2; - heap := Bss.address + Bss.size; stack := RTL.ram + ram; + Bss.size := IL.codes.bss + IL.codes.bss MOD 2; + DEC(stack, Bss.size); + Bss.address := stack; + DEC(stack, RTL.VarSize); + heap := RTL.ram; ASSERT(stack - heap >= StkReserve); adr := Code.address + 2; PutWord(stack, adr); diff --git a/source/MSP430RTL.ob07 b/source/MSP430RTL.ob07 index 899fb49..8f0ff9a 100644 --- a/source/MSP430RTL.ob07 +++ b/source/MSP430RTL.ob07 @@ -55,6 +55,8 @@ CONST StkReserve* = 40; + trap = 2; + TYPE @@ -63,7 +65,7 @@ TYPE VAR - ram*, trap*, int*: INTEGER; + ram*: INTEGER; rtl*: ARRAY 22 OF RECORD @@ -385,11 +387,9 @@ BEGIN Word1(1206H); (* PUSH R6 *) Word1(1205H); (* PUSH R5 *) Word1(1204H); (* PUSH R4 *) - Word2(4214H, trap); (* MOV trap(SR), R4 *) - Word1(9304H); (* TST R4 *) - Word1(2400H + 1); (* JZ L *) + Word2(4214H, sp); (* MOV sp(SR), R4 *) + Word2(4414H, trap); (* MOV trap(R4), R4 *) Word1(1284H); (* CALL R4 *) - (* L: *) Word2(04032H, 0F0H) (* MOV CPUOFF+OSCOFF+SCG0+SCG1, SR *) END; @@ -661,14 +661,12 @@ BEGIN END Used; -PROCEDURE Init* (pLabel, pWord, pCall: EMITPROC; ramSize: INTEGER); +PROCEDURE Init* (pLabel, pWord, pCall: EMITPROC); BEGIN Label := pLabel; Word := pWord; Call := pCall; ram := 200H; - trap := ram; - int := trap + 2 END Init;