@***************************************************************
@  STARTUP.ASM  für Betty-TV-Fernbedienung                     *
@  mit Philips LPC2220 und 2 externen Flash-ROMs               *
@                                                              *
@  die CPU kann max. 75 MHz, läuft mit 30 MHz,                 *
@  die Peripherie läuft mit 15 MHz                             *
@  Quarz = 10 MHz                                              *
@***************************************************************

.global     PixLane1        @ 2560 Bytes
.global     PixLane2        @ 2560 Bytes
.global     DirtyPages      @ DWORD
.global     Errors          @ DWORD
.global     ErrAddr
.global     Manifest
.global     CS_Area0
.global     CS_Area1
.global     CS_Area2
.global     CS_Area3
.global     LCD_CMD
.global     LCD_DATA
.global     Hard_Reset
.global     Soft_Reset
.global     EndOfRam
.global     abort_me


@ interne Resourcen:
@ ==================
@ 64 K RAM                     ab 40000000h..4000FFFFh
@ darin:
@ am RAM-Ende 2 Grafik-Puffer für das LCD zu je 2560 Bytes
@ darunter diverse Householding-Variablen
@ darunter die Stacks
@ darunter das Ende des frei nutzbaren RAMs


@ externe Resourcen:
@ Bank 0 = 1 MByte = EN29LV800 ab 80000000h..800FFFFFh
@ Bank 1 = LCD (128x160x2)        81000000h CMD
@                                 81000001h Data
@ Bank 2 = 1 MByte = EN29LV800 ab 82000000h..810FFFFFh
@ Bank 4 = ?

@ zum LCD:
@ ========
@ Die Breite ist 128 (X also 0..127) und die Höhe ist 160, (Y also 0..159).
@ Jedes Pixel hat 2 Bit, die in 2 verschiedenen Bytes angeordnet sind, also
@ quasi 2 Ebenen, die jeweils 1 Bit für jedes Pixel halten.

@ Es gibt einen ladbaren Adresspointer zum Lesen und Schreiben, der mit
@ jedem Lese/Schreibvorgang inkrementiert wird. Dieser Adresspointer hat 7 Bit,
@ kann also von 0..127 zählen. Das ist die Displaybreite.

@ In Y-Richtung gibt es 22 sogenannte Pages, von denen man eine per Kommando
@ wählen kann. 22*8=176 Pixels in Y-Richtung, von denen jedoch nur 160 benutzt werden.
@ Jede Page ist 8 Pixel hoch (entsprechend den 8 Bit in einem Byte)

@ Man kann per Hardware das LCD in X- und in Y-Richtung getrennt spiegeln.
@ Im Normalfalle ist die Orientierung so:
@ Pixel[0,0], also genz links oben ist in Page 0, dort im Byte 0, dort in Bit 0 auf beiden
@ Ebenen.
@ Pixel[127,159], also genz unten rechts ist in Page 19, dort im Byte 127, dort in Bit 7
@ auf beiden Ebenen.

@ hier im Startup-Code sind 2 Puffer (jeweils 128*160/8=2560 Bytes) definiert, die für das
@ GDI den zu beschreibenden Bildspeicher darstellen. Änderungen in diesem müssen anschließend
@ in das LCD übertragen werden.



@ 4 feste Speicherbänke:
.set	CS_Area0, 0x80000000          @ Flashrom 0, 1 MB, mit Betriebssystem
.set	CS_Area1, 0x81000000          @ LCD-Anschluß, nur 2 Bytes, siehe unten
.set	CS_Area2, 0x82000000          @ Flashrom 1, 1 MB, für sonstwas
.set	CS_Area3, 0x83000000          @ unbenutzt?

.set	LCD_CMD , 0x81000000
.set	LCD_DATA, 0x81000003

@ Bank Konfigurations-Register
.set	BCFG0   , 0xFFE00000
.set	BCFG1   , 0xFFE00004
.set	BCFG2   , 0xFFE00008
.set	BCFG3   , 0xFFE0000C


@ Bank Setupwerte
@ ===============

@ Bank 0 = ROM 0x80000000, 16 Bit, 70 ns
.set	b0_IDCY    ,  0         @ idles 0..15    = mindest CCLK's zwischen Rd und WR Zugriffen
.set	b0_WST1    ,  0         @ readwaits 0..31 +3 = Read-Waitstates in CCLK's
.set	b0_RBLE    ,  0         @ ByteLanesEnable: 0 = keine BLSx, 1 = BLS0..3 werden aktiviert
.set	b0_WST2    ,  2         @ writewaits (RAM) 0..31 +1 = Write-Waitstates in CCLK's
.set	b0_wprot   ,  0         @ 1 = Write protect
.set	b0_burst   ,  0         @ 1 = Burst-ROM
.set	b0_wide    ,  1         @ 0=byte, 1=word, 2=dword, 3=verboten

@ Bank 1 = LCD 0x81000000, 8 Bit, Speed=?
.set	b1_IDCY    ,  5         @ 0..15    = mindest CCLK's zwischen Rd und WR Zugriffen
.set	b1_WST1    ,  2         @ 0..31 +3 = Read-Waitstates in CCLK's
.set	b1_RBLE    ,  1         @ ByteLanesEnable: 0 = keine BLSx, 1 = BLS0..3 werden aktiviert
.set	b1_WST2    ,  2         @ 0..31 +1 = Write-Waitstates in CCLK's
.set	b1_wprot   ,  0         @ 1 = Write protect
.set	b1_burst   ,  0         @ 1 = Burst-ROM
.set	b1_wide    ,  0         @ 0=byte, 1=word, 2=dword, 3=verboten

@ Bank 2 = ROM 0x82000000, 16 Bit, 70 ns
.set	b2_IDCY    ,  0         @ 0..15    = mindest CCLK's zwischen Rd und WR Zugriffen
.set	b2_WST1    ,  0         @ 0..31 +3 = Read-Waitstates in CCLK's
.set	b2_RBLE    ,  0         @ ByteLanesEnable: 0 = keine BLSx, 1 = BLS0..3 werden aktiviert
.set	b2_WST2    ,  2         @ 0..31 +1 = Write-Waitstates in CCLK's
.set	b2_wprot   ,  0         @ 1 = Write protect
.set	b2_burst   ,  0         @ 1 = Burst-ROM
.set	b2_wide    ,  1         @ 0=byte, 1=word, 2=dword, 3=verboten

@ Bank 3 unbenutzt
.set	b3_IDCY    ,  0         @ 0..15    = mindest CCLK's zwischen Rd und WR Zugriffen
.set	b3_WST1    ,  0         @ 0..31 +3 = Read-Waitstates in CCLK's
.set	b3_RBLE    ,  0         @ ByteLanesEnable: 0 = keine BLSx, 1 = BLS0..3 werden aktiviert
.set	b3_WST2    ,  0         @ 0..31 +1 = Write-Waitstates in CCLK's
.set	b3_wprot   ,  0         @ 1 = Write protect
.set	b3_burst   ,  0         @ 1 = Burst-ROM
.set	b3_wide    ,  0         @ 0=byte, 1=word, 2=dword, 3=verboten

.set	ValForBCFG0,  b0_IDCY | (b0_WST1<<5) | (b0_RBLE<<10) | (b0_WST2<<11) | (b0_wprot<<26) | (b0_burst<<27) | (b0_wide<<28)
.set	ValForBCFG1,  b1_IDCY | (b1_WST1<<5) | (b1_RBLE<<10) | (b1_WST2<<11) | (b1_wprot<<26) | (b1_burst<<27) | (b1_wide<<28)
.set	ValForBCFG2,  b2_IDCY | (b2_WST1<<5) | (b2_RBLE<<10) | (b2_WST2<<11) | (b2_wprot<<26) | (b2_burst<<27) | (b2_wide<<28)
.set	ValForBCFG3,  b3_IDCY | (b3_WST1<<5) | (b3_RBLE<<10) | (b3_WST2<<11) | (b3_wprot<<26) | (b3_burst<<27) | (b3_wide<<28)




@ RAM und Stacks:
@ ===============
.set	Top_Ram          ,     0x40010000      @ der interne RAM geht von 40000000 bis 4000FFFF
.set	PixLane2         ,     Top_Ram - 2560  @ LCD-BWSP Ebene 2
.set	PixLane1         ,     PixLane2 - 2560 @ LCD-BWSP Ebene 1
.set	DirtyPages       ,     PixLane1 - 4    @ dword für geänderte LCD-Pages

.set	Errors           ,     DirtyPages - 4  @ Bitfeld zum Merken von Fehlern etc.
.set	ErrAddr          ,     Errors - 4

@ Stack-Sizes
@ ===========
@ definierte Stacks sind:
@ User und System (benutzen beide den User-Stack),
@ Supervisor, Abort, Undefined, FIQ, IRQ
@
.set	UNDEF_SS ,    48       @ RealMonitor braucht 48
.set	ABORT_SS ,    16       @ RealMonitor braucht 16
.set	FIQ_SS   ,     4
.set	IRQ_SS   ,   128
.set	SUPVI_SS ,   256       @ SWI Stack...
.set	USER_SS  ,  1024


@ die diversen Stacks
.set	Top_Stack   ,     ErrAddr - 4
.set	Undef_Stack ,     Top_Stack
.set	Abort_Stack ,     Undef_Stack - UNDEF_SS
.set	FIQ_Stack   ,     Abort_Stack - ABORT_SS
.set	IRQ_Stack   ,     FIQ_Stack   - FIQ_SS
.set	Supvi_Stack ,     IRQ_Stack   - IRQ_SS
.set	User_Stack  ,     Supvi_Stack - SUPVI_SS


.set	StartOfRam  ,     0x40000000
.set	EndOfRam    ,     User_Stack - USER_SS


@ Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs

.set	Mode_USER      ,     0x10
.set	Mode_FIQ       ,     0x11
.set	Mode_IRQ       ,     0x12
.set	Mode_SUPERVISOR,     0x13
.set	Mode_ABORT     ,     0x17
.set	Mode_UNDEF     ,     0x1B
.set	Mode_SYSTEM    ,     0x1F

.set	I_Bit          ,     0x80       @ when I bit is set, IRQ is disabled
.set	F_Bit          ,     0x40       @ when F bit is set, FIQ is disabled


@----------------------------------------------------------------------
@ VPBDIV = Taktteiler zwischen AMBA- und Peripherie-Bus (VPB)
@ nach Reset: VPB arbeitet auf 1/4 des AMBA-Taktes

.set	VPBDIV         ,     0xE01FC100  @ VPBDIV Addresse
.set	VPBDIV_Val     ,     0x00000002  @ 0 = 1/4@ 1 = 1:1@ 2 = 1/2

@ Phase Locked Loop (PLL) definitions
.set	PLL_BASE       ,     0xE01FC080  @ PLL Base Address
.set	PLLCON_OFS     ,     0x00        @ PLL Control Offset
.set	PLLCFG_OFS     ,     0x04        @ PLL Configuration Offset
.set	PLLSTAT_OFS    ,     0x08        @ PLL Status Offset
.set	PLLFEED_OFS    ,     0x0C        @ PLL Feed Offset
.set	PLLCON_PLLE    ,     (1<<0)      @ PLL Enable
.set	PLLCON_PLLC    ,     (1<<1)      @ PLL Connect
.set	PLLCFG_MSEL    ,     (0x1F<<0)   @ PLL Multiplier
.set	PLLCFG_PSEL    ,     (0x03<<5)   @ PLL Divider
.set	PLLSTAT_PLOCK  ,     (1<<10)     @ PLL Lock Status

@ PLLCFG:    7  6  5    4  3  2  1  0
@            - |PSEL | |____MSEL_____|
@ Fcpu = Fquarz * (MSEL+1)@
@ Fquarz ist hier 10 MHz. Wir wollen erstmal 30 MHz
@ original Betty: PLLCFG=0x42@ macht PSEL=3 und MSEL=2
@ also 30 MHz ist 3*10 MHz, also MSEL = 2 (ergibt Faktor 3)
.set	MSEL           ,    2     @ Fcpu = 10MHz * 3 = 30 MHz

@ Der VCO kann von 156 bis 320 MHz schwingen
@ VCO / P --> Prozessortakt CCLK, wobei P sich aus PSEL ergibt:
@ PSEL=0 --> P=1
@ PSEL=1 --> P=2
@ PSEL=2 --> P=4
@ PSEL=3 --> P=8
@ bei 30 MHz liegt nur PSEL=3 im Rahmen des VCO:
@ PSEL=3 --> P=8@  CCLK * 8 = 30MHz*8 --> 240 MHz
@ (120 MHz wäre zu wenig)
.set	PSEL           ,    3     @ ergibt :8

.set	PLLCFG_Val     ,    (PSEL << 5) + MSEL

@ Pin-Funktions-Selektions-Register
.set	PINSEL2        ,     0xE002C014




@ Restart-Gründe
@ ==============
.set	istKaltstart     ,   0
.set	istWarmstart     ,   1
.set	istRaise         ,   2
.set	istPrefetchErr   ,   4
.set	istUndefErr      ,   8
.set	istWrongSwi      ,  16
.set    istDabtErr       ,  32
@ alles >= 0x80000000 ist Abort



@ Area Definition and Entry Point
@ Startup Code must be linked first at Address at which it expects to run.

                .section  .text.startup
                .func     Vectors
                .arm


@ Interrupt-Tafel.
@ Die folgenden Befehle nebst den zugehörigen Adress-Literalen
@ werden vom Startup-Code in den internen RAM kopiert.
@ Interrupt-Trick: für IRQ und FIQ wird per Adressier-Trick
@ (negative Adresse zeigt auf die zugehörigen Register im AIC)
@ die tatsächlichen Handler-Adressen aus dem AIC ausgelesen
@ und dorthin verzweigt.
Vectors:        LDR     PC,Reset_Addr          @ 00h
                LDR     PC,Undef_Addr          @ 04h
                LDR     PC,SWI_Addr            @ 08h
                LDR     PC,Prefetch_Addr       @ 0Ch
                LDR     PC,DataAbort_Addr      @ 10h
                NOP                            @ 14h Signature!
                LDR     PC,[PC, #-0x0FF0]
                LDR     PC,FIQ_Addr


Reset_Addr:     .word   Hard_Reset
Undef_Addr:     .word   Undef_Handler
SWI_Addr:       .word   SWI_Handler
Prefetch_Addr:  .word   PrefetchAbort_Handler
DataAbort_Addr: .word   DataAbort_Handler
FIQ_Addr:       .word   FIQ_Handler
@ Ende der Interrupt-Tafel.
                .word     0
		.word     0


@
Manifest:       .ascii    "Betty Base 0.03 gcc\0x00"
                .align 4


@ Einstellwert für PINSEL2: mit CS1 und P3.0=A0
.set	wf_PINSEL2     ,   0xDE049D4

@----------------------------------------------------------------------
@ Hier geht es nach dem Reset los.
Hard_Reset:
     LDR     R0, =PLL_BASE          @ Configure and Enable PLL
     MOV     R1, #0xAA
     MOV     R2, #0x55
     MOV     R3, #PLLCFG_Val
     STR     R3, [R0, #PLLCFG_OFS]
     MOV     R3, #PLLCON_PLLE
     STR     R3, [R0, #PLLCON_OFS]
     STR     R1, [R0, #PLLFEED_OFS]
     STR     R2, [R0, #PLLFEED_OFS]

PLL_Loop:                            @ Wait until PLL Locked
     LDR     R3, [R0, #PLLSTAT_OFS]
     ANDS    R3, R3, #PLLSTAT_PLOCK
     BEQ     PLL_Loop

@ Switch to PLL Clock
     MOV     R3, #(PLLCON_PLLE  | PLLCON_PLLC)
     STR     R3, [R0, #PLLCON_OFS]
     STR     R1, [R0, #PLLFEED_OFS]
     STR     R2, [R0, #PLLFEED_OFS]

@ die allernötigsten Einstellungen an PINSEL und Bank-Config
     LDR     R0, =PINSEL2
     LDR     R1, =wf_PINSEL2
     STR     R1, [R0]

     LDR     R1, =ValForBCFG0
     LDR     R0, =BCFG0
     STR     R1, [R0]

     LDR     R1, =ValForBCFG1
     LDR     R0, =BCFG1
     STR     R1, [R0]

     LDR     R1, =ValForBCFG2
     LDR     R0, =BCFG2
     STR     R1, [R0]

     @ Bank 3 ist unbenutzt


@ internen RAM ablöschen
     LDR     R0, =StartOfRam
     MOV     R1, #0
     LDR     R2, =Top_Ram
iloop:
     STRB    R1, [R0], #1
     CMP     R0, R2                 @ RAM, Stacks und Kommandozeile
     BLT     iloop

@ hier werden die Stacks für die versch. Modi aufgesetzt.
     LDR     R0, =Top_Stack
                                    @  Enter Undefined Instruction Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_UNDEF | I_Bit | F_Bit
     MOV     SP, R0
     SUB     R0, R0, #UNDEF_SS

                                    @  Enter Abort Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_ABORT | I_Bit | F_Bit
     MOV     SP, R0
     SUB     R0, R0, #ABORT_SS

                                    @  Enter FIQ Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_FIQ | I_Bit | F_Bit
     MOV     SP, R0
     SUB     R0, R0, #FIQ_SS

                                    @  Enter IRQ Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_IRQ | I_Bit | F_Bit
     MOV     SP, R0
     SUB     R0, R0, #IRQ_SS

                                    @  Enter Supervisor Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_SUPERVISOR | I_Bit | F_Bit
     MOV     SP, R0
     SUB     R0, R0, #SUPVI_SS

                                    @ Fehler beim Kaltstart löschen
     LDR     R0, =Errors
     SUB     R1, R1, R1
     STR     R1, [R0]               @  Fehlerbits löschen

     B       Restart


@ Wiedereintrittspunkt für Soft-Reset
Soft_Reset:
     MOV     R1, #istWarmstart

@ Error-Bit in R1
Restart:
     LDR     R0, =ErrAddr
     STR     LR,[R0]
     LDR     R0, =Errors
     LDR     R2,[R0]
     ORR     R2,R2,R1
     STR     R2,[R0]


@ Übergang in 'User'-Mode mit freigegebenem IRQ und FIQ
UserMode:
     LDR     R0, =User_Stack
     MSR     CPSR_c, #Mode_USER
     MOV     SP, R0


@ ab hier im User-Mode. F- und I-Bits sind hier nicht mehr veränderbar.
@ Enter the C code
_main:
__main:
.global _main
.global __main
.global  __raise
.global E_exit

.extern  main
       LDR     R0, =main
       BX      R0

_sys_exit:
       B        Soft_Reset

@=============================================================================

.set VICVectAddr   , 0xFFFFF030     @ R=Vektoradresse, W=INT löschen


@ Interrupt-Behandlungsroutinen.
@ ==============================

@ Unbekannter Maschinenbefehl. Die CPU hat sich an einem Opcode verschluckt,
@ den sie nicht versteht.
Undef_Handler:          MOV     R1, #istUndefErr   @ Fehler-Bit für 'Errors' in R1 laden
                        B       Restart


@ Prefetch-Abort, wir sind auf eine Adresse gesprungen, die außerhalb aller
@ definierten Chipselect-Bereiche liegt
PrefetchAbort_Handler:  STMFD   SP!,{R0}        @ 'PUSH' R0
                        MOV     R1, #istPrefetchErr   @ Fehler-Bit für 'Errors' in R1 laden
                        B       Restart


@ Data-Abort, wir haben auf eine Adresse außerhalb aller definierten
@ Chipselect-Bereiche zugegriffen
@ Was machen wir? nen Error setzen und Warmstart...
DataAbort_Handler:	MOV     R1, #istDabtErr
                        B       Restart


@ Software-Interrupt.
@ Achtung! Die aufgerufenen Teile laufen im Supervisor-Modus und dürfen
@ ihrerseits KEINE Software-Interrupts verwenden!!
@ SWI-Handler a la Keil
.set      T_Bit, 0x20
.global   SWI_Handler

SWI_Handler:
                STMFD   SP!, {R12, LR}         @ Store R12, LR
                MRS     R12, SPSR              @ Get SPSR
                STMFD   SP!, {R8, R12}         @ Store R8, SPSR
                TST     R12, #T_Bit            @ Check Thumb Bit
                LDRNEH  R12, [LR,#-2]          @ Thumb: Load Halfword
                BICNE   R12, R12, #0xFF00      @        Extract SWI Number
                LDREQ   R12, [LR,#-4]          @ ARM:   Load Word
                BICEQ   R12, R12, #0xFF000000  @        Extract SWI Number

                LDR     R8, SWI_Count
                CMP     R12, R8
                BHS     SWI_Dead               @ Overflow

                ADR     R8, SWI_Table
                LDR     R12, [R8,R12,LSL #2]   @ Load SWI Function Address
                MOV     LR, PC                 @ Return Address
                BX      R12                    @ Call SWI Function

                LDMFD   SP!, {R8, R12}         @ Load R8, SPSR
                MSR     SPSR_cxsf, R12         @ Set SPSR
                LDMFD   SP!, {R12, PC}^        @ Restore R12 and Return

SWI_Dead:
		MOV     R1, #istWrongSwi       @ None Existing SWI
                B       Restart


.set  SWI_Cnt, (SWI_End-SWI_Table)/4
SWI_Count:       .word     SWI_Cnt

SWI_Table:
                .word  SWI_Dead                   @ 0   die ersten werden freigehalten
                .word  SWI_Dead                   @ 1   wegen evtl. RTOS
                .word  SWI_Dead                   @ 2
                .word  SWI_Dead                   @ 3
                .word  SWI_Dead                   @ 4
                .word  SWI_Dead                   @ 5
                .word  SWI_Dead                   @ 6
                .word  SWI_Dead                   @ 7

@ ab hier OS-Funktionen
                .word      Soft_Reset           @ 8 --> Restart

@ Importe aus dem GDI
                .extern    FillLanes
                .word      FillLanes            @ 9

                .extern    LichtAus
                .word      LichtAus             @ 10

                .extern    LichtEin
                .word      LichtEin             @ 11

                .extern    FlipDisplay
                .word      FlipDisplay          @ 12

                .extern    ScrBlt
                .word      ScrBlt               @ 13

                .extern    CgPixel_at
                .word      CgPixel_at           @ 14

                .extern    MoveTo
                .word      MoveTo               @ 15

                .extern    LineTo
                .word      LineTo               @ 16

                .extern    CgFillRect
                .word      CgFillRect           @ 17

                .extern    CgCh_at
                .word      CgCh_at              @ 18

                .extern    CgStr_at
                .word      CgStr_at             @ 19

                .extern    StringWidth
                .word      StringWidth          @ 20

                .extern    Get_dY
                .word      Get_dY               @ 21

                .extern    Get_Ascent
                .word      Get_Ascent           @ 22

                .extern    Get_Descent
                .word      Get_Descent          @ 23

                .extern    Get_dX
                .word      Get_dX               @ 24

                .extern    Get_Font
                .word      Get_Font             @ 25

                .extern    DispatchEvent
                .word      DispatchEvent        @ 26

                .extern    LocalToScreen
                .word      LocalToScreen        @ 27

                .extern    Umrande
                .word      Umrande              @ 28

                .extern    PanelKeyHandler
                .word      PanelKeyHandler      @ 29

                .extern    PanelEventHandler
                .word      PanelEventHandler    @ 30

                .extern    PanelDrawProc
                .word      PanelDrawProc        @ 31

                .extern    ButtonDrawProc
                .word      ButtonDrawProc       @ 32

                .extern    Messagebox
                .word      Messagebox           @ 33

                .extern    GetSetMenu
                .word      GetSetMenu           @ 34

                .extern    V24_Init
                .word      V24_Init             @ 35

                .extern    V24_Txfree
                .word      V24_Txfree           @ 36

                .extern    V24_CharOut
                .word      V24_CharOut          @ 37

                .extern    V24_StrOut
                .word      V24_StrOut           @ 38

                .extern    V24_CRLF
                .word      V24_CRLF             @ 39

                .extern    V24_CharAvail
                .word      V24_CharAvail        @ 40

                .extern    V24_CharIn
                .word      V24_CharIn		@ 41

                .extern    IsKeyAvailable
                .word      IsKeyAvailable	@ 42

                .extern    IsKeyPressed
                .word      IsKeyPressed		@ 43

                .extern    GetKey
                .word      GetKey		@ 44

                .extern    TranslateKeynum
                .word      TranslateKeynum      @ 45

                .extern    TastenZustand
                .word      TastenZustand       	@ 46

                .extern    CgPicture_at
                .word      CgPicture_at         @ 47

                .extern    CgCircle_at
                .word      CgCircle_at          @ 48

                .extern    Ich_selected
                .word      Ich_selected         @ 49

                .extern    StringCopy
                .word      StringCopy           @ 50

                .extern    StringAdd
                .word      StringAdd            @ 51

                .extern    Add_Delayed_Event
                .word      Add_Delayed_Event    @ 52


SWI_End:





@ NixTun-Handler für Interrupts
.global  IRQ_HandlerDummy
IRQ_HandlerDummy:
                STMFD   SP!,{R0}         @ 'PUSH' R0
                LDR     R0, =VICVectAddr @ Int löschen
				STR     R0, [R0]
				LDMFD   SP!,{R0}         @ 'POP' R0
                SUBS    PC,LR,#4



@ Handler für den FIQ:
@ Für den FIQ hat es eine Bank mit separaten Registern R8 ... R14
@ wenn man nur den separaten Registersatz benutzt,
@ braucht man keine Register auf dem Stack zu retten
@ dieser Handler macht erstmal nix.

FIQ_Handler:

                LDR     R12, =VICVectAddr @ Int löschen
				STR     R11, [R12]

fiq_done:		SUBS    PC,LR,#4          @ return from FIQ
@				LTORG




@ nur zum Export. Wird von mir nicht aktiv benutzt.
__raise:
       MOV      R1, #istRaise
       B        Restart

abort_me:
       ORR      R1,R0,#0x80000000      @ Param nach R1
       B        Restart

@       LTORG

.end
