diff --git a/Compiler b/Compiler index 7041fff..13ca719 100644 Binary files a/Compiler and b/Compiler differ diff --git a/Compiler.exe b/Compiler.exe index 05e7cc6..e7ad342 100644 Binary files a/Compiler.exe and b/Compiler.exe differ diff --git a/doc/MSP430.txt b/doc/MSP430.txt index f3b2a9b..eb00342 100644 --- a/doc/MSP430.txt +++ b/doc/MSP430.txt @@ -203,10 +203,9 @@ Oberon-реализациях выполнение такой операции Использование регистров общего назначения R4 - R15 R4 - R7: регистровый стэк (промежуточные значения выражений) - R8 - R12: не используются - R13: используется при обработке прерываний + R8 - R13: не используются R14: указатель кучи - R15: указатель кадра стэка + R15: используется при обработке прерываний ------------------------------------------------------------------------------ Вызов процедур и кадр стэка @@ -218,9 +217,8 @@ Oberon-реализациях выполнение такой операции Состояние стэка при выполнении процедуры: - меньшие адреса <- |var3|var2|var1|R15|PC|arg1|arg2|arg3| -> бОльшие адреса + меньшие адреса <- |var3|var2|var1|PC|arg1|arg2|arg3| -> бОльшие адреса - R15 - значение регистра R15 перед вызовом PC - значение регистра PC перед вызовом (адрес возврата) argX - параметры в порядке объявления (слева направо) varX - локальные переменные в порядке использования в процедуре @@ -230,30 +228,10 @@ Oberon-реализациях выполнение такой операции записи) занимают место в стэке в соответствии с их размером (с учетом выравнивания). - Адресация кадра стэка: - 0(R15) - предыдущее значение регистра R15 - 2(R15) - адрес возврата - 4(R15) - arg1 - 6(R15) - arg2 - -2(R15) - var1 - -4(R15) - var2 - Размещение локальных переменных зависит от их размеров и порядка использования, и в общем случае неопределенно. Если переменная не используется явно, то компилятор не выделяет для нее место в стэке. - Пролог процедуры: - PUSH R15 ; сохранить предыдущее значение - MOV SP, R15 ; настроить указатель кадра - PUSH #0 ; выделить место для локальных переменных с обнулением - PUSH #0 - ... - - Эпилог процедуры: - MOV R15, SP ; удалить локальные переменные (если есть) - POP R15 ; восстановить предыдущее значение - RET ; возврат - ------------------------------------------------------------------------------ Скрытые параметры процедур @@ -294,9 +272,8 @@ Oberon-реализациях выполнение такой операции 2000H + 400H - 3; (* JNZ L2 *) (* L1: *) - Для таких процедур компилятор не генерирует код пролога. Эпилог состоит -из единственной машинной команды "MOV @SP+, PC", она же "POP PC", -она же "RET". Способ передачи параметров и результата не изменяется. + Компилятор автоматически добавляет к такой процедуре команду RET. + Способ передачи параметров и результата не изменяется. Кодовые процедуры можно использовать также и для добавления в программу константных данных: @@ -341,12 +318,12 @@ SYSTEM. PUSH #30 ; поместить в стэк приоритет прерывания Label: - MOV SP, R13 ; настроить R13 на структуру данных прерывания (см. далее) + MOV SP, R15 ; настроить R15 на структуру данных прерывания (см. далее) PUSH R4 ; сохранить рабочие регистры (R4 - R7) ... PUSH R7 - PUSH R13 ; передать параметр interrupt в обработчик (см. далее) - PUSH @R13 ; передать параметр priority в обработчик (см. далее) + PUSH R15 ; передать параметр interrupt в обработчик (см. далее) + PUSH @R15 ; передать параметр priority в обработчик (см. далее) CALL int ; вызвать обработчик (см. далее) ADD #4, SP ; удалить из стэка параметры обработчика POP R7 ; восстановить рабочие регистры (R7 - R4) diff --git a/source/MSP430.ob07 b/source/MSP430.ob07 index c43a63b..e28eabf 100644 --- a/source/MSP430.ob07 +++ b/source/MSP430.ob07 @@ -24,7 +24,7 @@ CONST R4 = 4; R5 = 5; R6 = 6; R7 = 7; - IR = 13; HP = 14; BP = 15; + HP = 14; IR = 15; ACC = R4; @@ -108,6 +108,8 @@ VAR IdxWords: RECORD src, dst: INTEGER END; + StkCnt: INTEGER; + PROCEDURE EmitLabel (L: INTEGER); VAR @@ -254,7 +256,8 @@ BEGIN ELSE Op1(opPUSH, PC, sINCR); EmitWord(imm) - END + END; + INC(StkCnt) END PushImm; @@ -376,13 +379,15 @@ END Fixup; PROCEDURE Push (reg: INTEGER); BEGIN - Op1(opPUSH, reg, sREG) + Op1(opPUSH, reg, sREG); + INC(StkCnt) END Push; PROCEDURE Pop (reg: INTEGER); BEGIN - Op2(opMOV, incr(SP), reg) + Op2(opMOV, incr(SP), reg); + DEC(StkCnt) END Pop; @@ -430,7 +435,8 @@ BEGIN EmitCall(RTL.rtl[proc].label); RTL.Used(proc); IF params > 0 THEN - Op2(opADD, imm(params * 2), SP) + Op2(opADD, imm(params * 2), SP); + DEC(StkCnt, params) END END CallRTL; @@ -582,6 +588,11 @@ BEGIN END Neg; +PROCEDURE LocalOffset (offset: INTEGER): INTEGER; + RETURN (offset + StkCnt - ORD(offset > 0)) * 2 +END LocalOffset; + + PROCEDURE translate; VAR cmd, next: COMMAND; @@ -623,6 +634,7 @@ BEGIN |IL.opSADR_PARAM: Op1(opPUSH, PC, sINCR); + INC(StkCnt); EmitWord(param2); Reloc(RDATA) @@ -634,6 +646,7 @@ BEGIN |IL.opONERR: PushImm(param2); + DEC(StkCnt); EmitJmp(opJMP, param1) |IL.opLEAVEC: @@ -641,12 +654,8 @@ BEGIN |IL.opENTER: ASSERT(R.top = -1); - + StkCnt := 0; EmitLabel(param1); - - Push(BP); - MovRR(SP, BP); - IF param2 > 8 THEN Op2(opMOV, imm(param2), R4); L := NewLabel(); @@ -672,14 +681,11 @@ BEGIN END; drop END; - ASSERT(R.top = -1); - + ASSERT(StkCnt = param1); IF param1 > 0 THEN - MovRR(BP, SP) + Op2(opADD, imm(param1 * 2), SP) END; - - Pop(BP); Pop(PC) |IL.opRES: @@ -688,7 +694,8 @@ BEGIN |IL.opCLEANUP: IF param2 # 0 THEN - Op2(opADD, imm(param2 * 2), SP) + Op2(opADD, imm(param2 * 2), SP); + DEC(StkCnt, param2) END |IL.opCONST: @@ -724,14 +731,14 @@ BEGIN |IL.opLADR: reg1 := GetAnyReg(); - MovRR(BP, reg1); - Op2(opADD, imm(param2 * 2), reg1) + Op2(opMOV, imm(LocalOffset(param2)), reg1); + Op2(opADD, SP * 256, reg1) |IL.opLLOAD8: - Op2(opMOV + BW, src_x(param2 * 2, BP), GetAnyReg()) + Op2(opMOV + BW, src_x(LocalOffset(param2), SP), GetAnyReg()) |IL.opLLOAD16, IL.opVADR: - Op2(opMOV, src_x(param2 * 2, BP), GetAnyReg()) + Op2(opMOV, src_x(LocalOffset(param2), SP), GetAnyReg()) |IL.opGLOAD8: Op2(opMOV + BW, src_x(param2, SR), GetAnyReg()); @@ -751,12 +758,12 @@ BEGIN |IL.opVLOAD8: reg1 := GetAnyReg(); - Op2(opMOV, src_x(param2 * 2, BP), reg1); + Op2(opMOV, src_x(LocalOffset(param2), SP), reg1); Op2(opMOV + BW, indir(reg1), reg1) |IL.opVLOAD16: reg1 := GetAnyReg(); - Op2(opMOV, src_x(param2 * 2, BP), reg1); + Op2(opMOV, src_x(LocalOffset(param2), SP), reg1); Op2(opMOV, indir(reg1), reg1) |IL.opSAVE, IL.opSAVE16: @@ -816,11 +823,11 @@ BEGIN END |IL.opLADR_SAVEC: - Op2(opMOV, imm(param2), dst_x(param1 * 2, BP)) + Op2(opMOV, imm(param2), dst_x(LocalOffset(param1), SP)) |IL.opLADR_SAVE: UnOp(reg1); - Op2(opMOV, reg1 * 256, dst_x(param2 * 2, BP)); + Op2(opMOV, reg1 * 256, dst_x(LocalOffset(param2), SP)); drop |IL.opGADR_SAVEC: @@ -975,19 +982,19 @@ BEGIN drop |IL.opLADR_INCC, IL.opLADR_INCCB: - Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), dst_x(param1 * 2, BP)) + Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), dst_x(LocalOffset(param1), SP)) |IL.opLADR_DECCB: - Op2(opSUB + BW, imm(param2), dst_x(param1 * 2, BP)) + Op2(opSUB + BW, imm(param2), dst_x(LocalOffset(param1), SP)) |IL.opLADR_INC, IL.opLADR_INCB: UnOp(reg1); - Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, dst_x(param2 * 2, BP)); + Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, dst_x(LocalOffset(param2), SP)); drop |IL.opLADR_DEC, IL.opLADR_DECB: UnOp(reg1); - Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, dst_x(param2 * 2, BP)); + Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, dst_x(LocalOffset(param2), SP)); drop |IL.opPUSHT: @@ -1024,6 +1031,7 @@ BEGIN UnOp(reg1); PushAll(0); Op1(opPUSH, reg1, sIDX); + INC(StkCnt); EmitWord(-2); PushImm(param2); CallRTL(RTL._guardrec, 2); @@ -1347,6 +1355,7 @@ BEGIN UnOp(reg1); PushAll_1; Op1(opPUSH, PC, sINCR); + INC(StkCnt); EmitWord(param2); Reloc(RDATA); Push(reg1); @@ -1426,8 +1435,10 @@ BEGIN END |IL.opVADR_PARAM: - Op1(opPUSH, BP, sIDX); - EmitWord(param2 * 2) + reg1 := GetAnyReg(); + Op2(opMOV, src_x(LocalOffset(param2), SP), reg1); + Push(reg1); + drop |IL.opNEW: PushAll(1); @@ -1499,8 +1510,8 @@ BEGIN |IL.opLADR_INCL, IL.opLADR_EXCL: PushAll(1); - MovRR(BP, ACC); - Op2(opADD, imm(param2 * 2), ACC); + MovRR(SP, ACC); + Op2(opADD, imm(LocalOffset(param2)), ACC); Push(ACC); IF opcode = IL.opLADR_INCL THEN CallRTL(RTL._incl, 2) @@ -1509,10 +1520,10 @@ BEGIN END |IL.opLADR_INCLC: - Op2(opBIS, imm(ORD({param2})), dst_x(param1 * 2, BP)) + Op2(opBIS, imm(ORD({param2})), dst_x(LocalOffset(param1), SP)) |IL.opLADR_EXCLC: - Op2(opBIC, imm(ORD({param2})), dst_x(param1 * 2, BP)) + Op2(opBIC, imm(ORD({param2})), dst_x(LocalOffset(param1), SP)) END; diff --git a/source/UTILS.ob07 b/source/UTILS.ob07 index 2d1df78..8e82b18 100644 --- a/source/UTILS.ob07 +++ b/source/UTILS.ob07 @@ -24,7 +24,7 @@ CONST max32* = 2147483647; vMajor* = 1; - vMinor* = 18; + vMinor* = 19; FILE_EXT* = ".ob07"; RTL_NAME* = "RTL";