mikroPascal

Чем больше я им пользуюсь, тем сильнее желание снести его нахрен. Тупой и ограниченный, оптимизирует довольно паршиво, регулярно генерит кривой код на ровном месте. Отладка тоже практически отсутствует.


Вот так, например, mP8051 2.2 генерит вызов функции в одном из модулей (причем в остальных местах все нормально):
MOV A, R1
ANL A, #127
MOV _rtAddTask+0, A
LCALL _rtAddTask+0

В третьей строчке вместо _rtAddTask (адрес вызываемой функции) должно быть FARG_rtAddTask_Task — адрес аргумента. В результате аргумент отправляется в левую область ОЗУ, а функция вызывается с аргументом, оставшимся от последнего нормального вызова. И это далеко не первый случай.

Алсо, так и не понял как на нем (mikroPascal for 8051 2.2 — самый свежий) решить две задачки:
  • Вызвать функцию из инлайнового асма. Строчка «MOV FARG_rtAddTask_Task, A» не компилируется.
  • Сделать табличку функций или переходов (т.е. вызов функции по ее индексу в некоторой таблице).
Кто-нибудь знает, как их решить?

P.S. Свежий mP for AVR получше, и даже почти не лажает при компиляции. Почти.
UPD: А вот, кстати, шедевр оптимизации от него:
;25QFlash.mpas,57 ::                 SPIDDR:=SPIDDR or (1 shl SPI_MOSI) or (1 shl SPI_SCK) or (1 shl SPI_SS);
        IN         R16, DDRB+0
        ORI        R16, 32
        ORI        R16, 128
        ORI        R16, 16
        OUT        DDRB+0, R16


UPD:

Вот теперь оно компилируется без ошибок компилятора!

procedure rtStart;
var
  CurTask: Byte;
begin
  asm
    SETB TR0_bit                                    ; Start T/C0
    SETB EA_bit                                     ; Enable interrupts
    MOV rtStart_CurTask, #0                         ; CurTask:=0
  rtStart_MainLoop:
    JNB rtQueueOverflow, rtStart_NoQueueOverflow    ; if not rtQueueOverflow then goto NoQueueOverflow
    MOV R0, urtos_CallTask+2                        ; R0:=@FARG_CallTask_Task
    MOV @R0, #0xFF                                                                                                 ; SYNC = rtEventQueueOverflow
    MOV R0, urtos_CallTask                          ; R0:R1:=@CallTask
    MOV R1, urtos_CallTask+1
    ACALL ___DoIFC                                  ; CallTask(rtEventQueueOverflow)
  rtStart_NoQueueOverflow:
    JNB fUpdate, rtStart_NoUpdate                   ; if not fUpdate then gotoNoUpdate
    CLR fUpdate                                     ; fUpdate:=0
    MOV R2, #8                                      ; R2{i}:=TimersQueueSize                                       ; SYNC = TimersQueueSize
  rtStart_TimersQueueLoop:
    MOV A, R2                                       ; Calculate timer address
    CLR C
    RLC A
    MOV R0, A
    MOV A, #urtos_TimersQueue-2
    ADD A, R0
    MOV R1, A                                       ; R1{PCurTimer}:=2*i+@TimersQueue-2
    MOV A, @R1                                      ; ACC:=PCurTimer^.Task
    JNB ACC.7, rtStart_SkipTimer                    ; if not Task.fActive then goto SkipTimer                      ; SYNC = fActive
    MOV R0, R1                                      ; R0:=@(PCurTimer^.Timer)
    INC R0
    MOV A, @R0
    JZ rtStart_AddTimerTask                         ; if PCurTask^.Timer=0 then goto AddTimerTask
    DEC A                                           ; PTimer^.Timer:=PTimer^.Timer-1
    MOV @R0, A
    SJMP rtStart_SkipTimer                          ; goto SkipTimer
  rtStart_AddTimerTask:
    MOV A, @R1                                      ; ACC:=PCurTask^.Task
    MOV @R1, #0                                     ; PCurTask^.Task:=0
    ANL A, #0x7F                                                                                                   ; SYNC = TaskMask
    MOV R1, A                                       ; R1{Task}:=ACC or TaskMask
    MOV R3, #0                                      ; R3{j}:=0
  rtStart_AddTaskLoop:
    CJNE R3, #12, rtStart_NoOverflow                ; if j<>TasksQueueSize then goto NoOverflow                    ; SYNC = TasksQueueSize
    SETB rtQueueOverflow                            ; rtQueueOverflow:=1
  rtStart_NoOverflow:
    MOV A, #urtos_TasksQueue                        ; R0{PCurTask}:=@TasksQueue+j
    ADD A, R3
    MOV R0, A
    INC R3                                          ; Inc(j)
    MOV A, @R0
    JB ACC.7, rtStart_AddTaskLoop                   ; if PCurTask.fActive then goto AddTaskLoop                    ; SYNC = fActive
    MOV A, R1
    SETB ACC.7                                      ; Task.fActive:=1                                              ; SYNC = fActive
    MOV @R0, A                                      ; PCurTask^:=Task
  rtStart_SkipTimer:
    DJNZ R2, rtStart_TimersQueueLoop                ; Dec(i); if i<>0 then goto TimersQueueLoop
    SJMP rtStart_MainLoop                           ; goto MainLoop
  rtStart_NoUpdate:
    MOV A, #urtos_TasksQueue                        ; R0{PCurTask}:=@TasksQueue+CurTask
    ADD A, rtStart_CurTask
    MOV R0, A
    MOV A, @R0                                      ; A{Task}:=PCurTask^
    JNB ACC.7, rtStart_SkipTask                     ; if not Task.fActive then goto SkipTask                       ; SYNC = fActive
    MOV @R0, #0                                     ; PCurTask^:=0
    ANL A, #0x7F                                    ; Task:=Task or TaskMask                                       ; SYNC = TaskMask
    MOV R0, urtos_CallTask+2                        ; R0:=@FARG_CallTask_Task
    MOV @R0, A                                      ; FARG_CallTask_Task:=Task
    MOV R0, urtos_CallTask                          ; R0:R1:=@CallTask
    MOV R1, urtos_CallTask+1
    ACALL ___DoIFC                                  ; CallTask(Task)
  rtStart_SkipTask:
    INC rtStart_CurTask                             ; Inc(CurTask)
    MOV A, rtStart_CurTask
    CJNE A, #12, rtStart_MainLoop                   ; if CurTask<>TaskQueueSize then goto MainLoop                 ; SYNC = TasksQueueSize
    MOV rtStart_CurTask, #0                         ; CurTask:=0
    {$IFDEF RTOS_DEBUG}
    SETB fUpdate                                    ; fUpdate:=1 //debug hack
    {$ENDIF}
    SJMP rtStart_MainLoop                           ; goto MainLoop
  end;
end;


Алсо, задачку «таблица функций» тоже решил (точнее, я ее решил еще на момент написания поста, но прямым это решение не назовешь):

procedure CallTask(Task: Byte);
begin
  asm
    MOV A, FARG_CallTask_Task
    CJNE A, #0xFF, CallTask_L1
    MOV P1, #0xFF
    MOV P3, #0xFF
    CLR BeepPin
  CallTask_FFUUUU:
    SJMP CallTask_FFUUUU
  CallTask_L1:
    CLR C
    RLC A
    CLR C
    RLC A
    ADD A, #5
    ACALL CallTask_L2
  CallTask_L2:
    POP DPH
    POP DPL
    JMP @A+DPTR
    LCALL Tasks_UpdateDisplay
    RET
    LCALL Tasks_BeepTimer
    RET
    LCALL Tasks_MainTimer
    RET
    LCALL Tasks_MainTimerComplete
    RET
    LCALL Tasks_DisplayDriver
    RET
    LCALL Tasks_ButtonsDriver
    RET
    LCALL Tasks_SClick
    RET
    LCALL Tasks_SPress
    RET
    LCALL Tasks_MClick
    RET
    LCALL Tasks_Beep2Timer
    RET
    LCALL Tasks_ResetDisplayTimer
    RET
  {case Task of
    tUpdateDisplay: UpdateDisplay;
    tBeepTimer: BeepTimer;
    tMainTimer: MainTimer;
    tMainTimerComplete: MainTimerComplete;
    tDisplayDriver: DisplayDriver;
    tButtonsDriver: ButtonsDriver;
    tSClick: SClick;
    tSPress: SPress;
    tMClick: MClick;
    tBeep2Timer: Beep2Timer;
    tResetDisplayTimer: ResetDisplayTimer;
    rtEventQueueOverflow: begin
      P1:=$FF;
      P3:=$FF;
      BeepPin:=0;
      while true do;
    end;}
  end;
end;

Закомментированный вариант тоже работает, но весит в скомпилированном виде вдвое больше.

Короче, нафиг этот кактус. Здравствуй, Кристалл-и-Корпус С, я был неправ, обойдя тебя вниманием.
  • +1
  • 18 апреля 2011, 07:33
  • Vga

Комментарии (13)

RSS свернуть / развернуть
Чем больше я им пользуюсь, тем сильнее желание снести его нахрен. Тупой и ограниченный, оптимизирует довольно паршивенько, регулярно генерит кривой код.
Дык у него даже название с ошибкой ;)
0
А великий и могучий Си, почему не жалуете?
0
Потому что паскаль люблю. Но увы, этот крив и убог. Так что придется делать на С.
Дык у него даже название с ошибкой ;)
Дык немцы же.
0
Болгары вроде бы
0
И правда. Спутал значит с кем-то.
0
Не, нифига, Сербы они — центральный офис в Белграде. Хренасе.
0
Болгары — Olimex, а то сербы, ага =)
0
Перетащил проектик на великий и могучий (в варианте от кейла). Бинарник похудел в полтора раза. Называть оптимизатор микропаскаля хорошим после этого язык не поворачивается (хотя и до этого поглядывание в листинг вызывало большие сомнения, даже при том, что с МК на ассемблере я не работал). И ошибки компилятора исчезли (за исключением одного места, где условие почему-то не срабатывало, хотя в исходном коде ошибки не нашел).
0
«Одно слово — румын! — Так он болгарин. — Да?! Какая разница?» (c) Брат-2 :))
+1
Шестую версию кто-нибудь уже обкатал?
0
5.60 довольно стабильна, но качество компилятора в целом отбивает желание его щупать даже нахаляву.
А крек на шестую уже есть?
0
Собственно, мне не слишком важна оптимизация кода. Лишь бы они там свои залипухи поправили.
0
Однако, текущая уже 6.0.1
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.