//SWI dispatcher v1.1 (C)2006 by Rst7/CBSIE


                   EXTERN  SWILIB
	           EXTERN  pLIB_TOP
	           EXTERN  FUNC_ABORT
                   
	           RSEG	   FSWI_PATCH1:CODE:ROOT
                   
	           CODE32

	           LDR	   PC, main_jumper
        
#ifndef NEWSGOLD
                   RSEG	   FSWI_PATCH3:DATA
	           DC8     0x00
#endif

	           RSEG	   FSWI_PATCH2:DATA(2)

       main_jumper:
	           DC32    main

	           RSEG    CODE:CODE
                   
	           CODE32
                   
           nullsub:
	           BX	   LR
                   
              main:
	           LDR	   R1, [SP, #0x00]      // Берем CPSR
	           TST     R1, #0x20	        // Проверяем на THUMB (установку T - бита)
	           ADREQ   R2, arm_jumper       // Берем адрес джампера
	           BEQ	   arm_mode
                   
	           CMP	   R0, #199	        // Служебный SWI для длинной библиотеки
	           LDREQH  R0, [LR], #2	        // Зацепляем второе слово (длинный номер) c пропуском DW
                   STREQ   LR, [SP, #0x14]      // Сохраняем временно адрес возврата (если захочем данные)
	           ADD	   LR, LR, #0x01        // Устанавливаем бит 0, если THUMB
	           ADR	   R2, thumb_jumper     // Берем адрес джампера
                   
          arm_mode:
	           LDR	   R1, =pLIB_TOP        // Указатель на таблицу адресов
	           LDR	   R1, [R1]
	           CMP	   R1, #0x00
	           LDREQ   R1, =Library
	           BIC	   R3, R0, #0x8000
                   CMP	   R3, #4096
                   BHI	   exit
                   
	           TST	   R0,  #0x8000		// А не адрес нам надо получить?
	           STMEQFD SP!, {LR}		// Копируем адрес возврата из LR_svc только если вызов функции
	           LDMEQFD SP!, {LR}^		// в LR_usr, он будет использован вызываемой функцией
	           LDR     R12, [R1, R3, LSL#2]	// Берем адрес функции
	           STRNE   R12, [SP, #4]	// пишем адрес в R0(стек)
    /* ADD */      MOV     R1,   LR
	           
                   BNE	  exit
	           CMP	  R12, #0xFFFFFFFF
	           LDREQ  R2, =FUNC_ABORT
	           STREQ  R0, [SP, #4]
	           STR	  R2, [SP, #0x14]	// Пишем адрес джампера для возврата в стеке (PC)
                   
                   
             
             exit:
	           LDMFD  SP!, {R0}
	           MSR	  SPSR_cf, R0
	           LDMFD  SP!, {R0-R3,PC}^
      
        arm_jumper:
	           BX	  R12
                   
	           CODE16
                   
      thumb_jumper:
	           BX	R12
                   
	           CODE32
//  Собственно библиотека

	           RSEG    LIBR: DATA(2)
	           PUBLIC  Library
                   
           Library:

	           END
