home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 2 / AUCD2.iso / program / vista.arc / c / tasm < prev    next >
Text File  |  1996-02-01  |  12KB  |  501 lines

  1. // **************************************************************************
  2. //                     Copyright 1996 David Allison
  3. //
  4. //             VV    VV    IIIIII     SSSSS     TTTTTT       AA
  5. //             VV    VV      II      SS           TT       AA  AA
  6. //             VV    VV      II        SSSS       TT      AA    AA
  7. //              VV  VV       II           SS      TT      AAAAAAAA
  8. //                VV       IIIIII     SSSS        TT      AA    AA
  9. //
  10. //                    MULTI-THREADED C++ WIMP CLASS LIBRARY
  11. //                                for RISC OS
  12. // **************************************************************************
  13. //
  14. //             P U B L I C    D O M A I N    L I C E N C E
  15. //             -------------------------------------------
  16. //
  17. //     This library is copyright. You may not sell the library for
  18. //     profit, but you may sell products which use it providing
  19. //     those products are presented as executable code and are not
  20. //     libraries themselves.  The library is supplied without any
  21. //     warranty and the copyright owner cannot be held responsible for
  22. //     damage resulting from failure of any part of this library.
  23. //
  24. //          See the User Manual for details of the licence.
  25. //
  26. // *************************************************************************
  27.  
  28.  
  29. //
  30. // assembly language for thread package
  31. //
  32.  
  33. #include <kernel.h>
  34. #include <string.h>
  35.  
  36. #define XEasyDebug_RegisterThreads  0x8304a|0x20000
  37. #define XEasyDebug_YieldThread      0x8304b|0x20000
  38.  
  39. #pragma asm
  40.  
  41. IMPORT context_switch__13ThreadManagerFv
  42. IMPORT start2__6ThreadFv
  43.  
  44. ;
  45. ; call the start2 member function for a thread.  This actually starts the thread
  46. ; running
  47. ;
  48.  
  49. ; entry:
  50. ;   R0 = thread
  51.  
  52. .thread_call_start2 EXPORT thread_call_start2
  53.         B start2__6ThreadFv
  54.  
  55. .thread_get_time EXPORT thread_get_time
  56.         STMFD SP!,{link}                  ; may be called in SVC mode
  57.         SWI OS_ReadMonotonicTime
  58.         LDMFD SP!,{PC}^
  59.  
  60.  
  61. #define Int_bit (1 << 27)
  62.  
  63. #define USR_mode 0
  64. #define FIQ_mode 1
  65. #define IRQ_mode 2
  66. #define SVC_mode 3
  67.  
  68.  
  69. ;
  70. ; claim the callback vector
  71. ;
  72.  
  73. ; entry:
  74. ;   R0 = thread manager address.  This is passed to the callback in R12
  75.  
  76. .thread_claim_callback
  77.     EXPORT thread_claim_callback
  78.         STMFD SP!,{R0-R3,link}
  79.         MOV R2,R0
  80.     MOV R0,#7
  81.     ADR R1,callback
  82.     LDR R3,thread_callback_regs
  83.     SWI XOS_ChangeEnvironment
  84.     STR R1,old_callback
  85.     STR R2,old_callback_r12
  86.     STR R3,old_callback_regs
  87.     LDMFD SP!,{R0-R3,PC}^
  88.  
  89. .old_callback
  90.     DCD 0
  91. .old_callback_r12
  92.     DCD 0
  93. .old_callback_regs
  94.     DCD 0
  95.  
  96.  
  97. ;
  98. ; release the callback vector
  99. ;
  100.  
  101.  
  102. .thread_release_callback
  103.     EXPORT thread_release_callback
  104.         STMFD SP!,{R0-R3,link}
  105.     MOV R0,#7
  106.     LDR R1,old_callback
  107.     LDR R2,old_callback_r12
  108.     LDR R3,old_callback_regs
  109.     SWI XOS_ChangeEnvironment
  110.     LDMFD SP!,{R0-R3,PC}^
  111.  
  112. ;
  113. ; start a ticker which will set the callback flag every clock tick
  114. ;
  115.  
  116. ; entry:
  117. ;   R0 = address of thread manager
  118.  
  119. .thread_start_ticker
  120.     EXPORT thread_start_ticker
  121.         LDR R2,alien_control
  122.         CMP R2,#0
  123.         MOVNES PC,link
  124.         STMFD SP!,{R0-R2,link}
  125.         MOV R2,R0
  126.     MOV R0,#1
  127.     STR R0,thread_worksemaphore
  128.     LDR R0,thread_poll_rate
  129.     ADR R1,call_every
  130.     SWI XOS_CallEvery
  131.     LDMFD SP!,{R0-R2,PC}^
  132.  
  133. ;
  134. ; stop the ticker running
  135. ;
  136.  
  137. ; entry:
  138. ;   R0 = thread manager
  139.  
  140. .thread_stop_ticker
  141.     EXPORT thread_stop_ticker
  142.         LDR R2,alien_control
  143.         CMP R2,#0
  144.         MOVNES PC,link
  145.         STMFD SP!,{R0-R1,link}
  146.         MOV R1,R0
  147.     ADR R0,call_every
  148.     SWI XOS_RemoveTickerEvent
  149.     LDMFD SP!,{R0-R1,PC}^
  150.  
  151. ;
  152. ; init the thread system for use with a debugger
  153. ;
  154.  
  155. ; entry:
  156. ;   R0 = thread manager
  157.  
  158. .thread_init EXPORT thread_init
  159.         STMFD SP!,{R0-R8,link}
  160.         MOV R5,R0
  161.         BL claim_heap_modifiers
  162.         ADR R0,thread_worksemaphore
  163.         LDR R1,ctx_swtch
  164.         ADR R2,thread_callback_regs
  165.         LDR R3,thread_poll_rate
  166.     ADR R4,thread_system_running
  167.     SWI XEasyDebug_RegisterThreads
  168.     MOVVS R1,#0                           ; no SWI: not under control
  169.     STRVS R1,alien_control
  170.     LDMVSFD SP!,{R0-R8,PC}^
  171.     CMP R0,#2                             ; module running?
  172.     MOVEQ R0,#1                           ; yes, under control
  173.     MOVNE R0,#0                           ; no, we're on our own
  174.     STR R0,alien_control
  175.     LDMFD SP!,{R0-R8,PC}^
  176.  
  177. ; this variable tells us whether we are being controlled by some outside influence
  178. ; EasyDebug controls the threads for us if so
  179.  
  180. .alien_control
  181.         DCD 0
  182.  
  183. .ctx_swtch
  184.         DCD context_switch__13ThreadManagerFv
  185.  
  186. .thread_system_running
  187.     EXPORT thread_system_running
  188.         DCD 0
  189.  
  190. .thread_worksemaphore          ; flag for callbacks
  191.         EXPORT thread_worksemaphore
  192.     DCD 0
  193.  
  194. .thread_callback_regs          ; current register save area
  195.     EXPORT thread_callback_regs
  196.     DCD 0
  197.  
  198. .thread_poll_rate              ; quantum poll rate
  199.         EXPORT thread_poll_rate
  200.         DCD 0
  201.  
  202. ;
  203. ; disable interrupts by setting the semaphore to non zero
  204. ;
  205.  
  206. .thread_disable_ints
  207.         EXPORT thread_disable_ints
  208.     MOV R0,#1
  209.     B write_ints
  210.  
  211. ;
  212. ; enable the interrupts by setting the semaphore to 0
  213.  
  214. ;
  215. .thread_enable_ints
  216.     EXPORT thread_enable_ints
  217.     MOV R0,#0
  218. .write_ints
  219.     STR R0,thread_worksemaphore
  220.     MOVS PC,link
  221.  
  222. .int_state
  223.     LDR R0,thread_worksemaphore
  224.     MOVS PC,link
  225. ;
  226. ; the ticker calls this every clock tick
  227. ;
  228.  
  229. .call_every
  230.         STMFD SP!,{R0,R1,link}
  231.     LDR R0,thread_worksemaphore
  232.     ADD R0,R0,#1
  233.     STR R0,thread_worksemaphore
  234.     CMP R0,#1
  235.     LDMNEFD SP!,{R0,R1,PC}^
  236.     MOV R1,pc                                 ; save current processor state
  237.     TEQP pc,#Int_bit+SVC_mode                  ; disable processor interrupts
  238.     MOV R0,R0
  239.     STMFD SP!,{link}
  240.     MOV R0,R12                                ; load thread manager
  241.     BL thread_claim_callback                  ; claim the callbacks
  242.     SWI XOS_SetCallBack                        ; set the OS callback flag
  243.     LDMFD SP!,{link}
  244.     TEQP R1,#0                                ; restore processor state
  245.     MOV R0,R0
  246.     LDMFD SP!,{R0,R1,PC}^
  247.  
  248. ;
  249. ; called in usr mode by a thread wishing to give up the processor
  250. ;
  251.  
  252. ; entry:
  253. ;   R0 = thread manager
  254.  
  255. .thread_yield
  256.         EXPORT thread_yield
  257.         LDR R1,alien_control
  258.         CMP R1,#0
  259.         SWINE XEasyDebug_YieldThread
  260.         MOVNES PC,link
  261.     STMFD SP!,{R0-R2,link}
  262.     MOV R1,#1
  263.     STR R1,thread_worksemaphore
  264.     BL thread_claim_callback
  265.      SWI XOS_SetCallBack
  266.      MOV R0,#0
  267.      MOV R1,#1
  268.     SWI XOS_Byte                        ; force a callback
  269.     LDMFD SP!,{R0-R2,PC}^
  270.  
  271. ;
  272. ; this is called when the OS is returning from SVC mode to USR mode
  273. ;
  274.  
  275. .callback
  276.         MOV R0,#1
  277.     STR R0,thread_worksemaphore         ; disable callbacks
  278.  
  279.     TEQP PC,#SVC_mode                   ; enable ints
  280.     MOV R0,R0
  281.     MOV R4,R12                         ; save thread manager
  282.         BL thread_release_callback         ; release the callback handler
  283.  
  284. ; save floating point regs in save area
  285.  
  286.         LDR R1,thread_callback_regs
  287.         ADD R1,R1,#16*4
  288.         STFE F0,[R1,#0]
  289.         STFE F1,[R1,#12]
  290.         STFE F2,[R1,#12*2]
  291.         STFE F3,[R1,#12*3]
  292.         STFE F4,[R1,#12*4]
  293.         STFE F5,[R1,#12*5]
  294.         STFE F6,[R1,#12*6]
  295.         STFE F7,[R1,#12*7]
  296.     RFS R0                             ; read floating status
  297.     STR R0,[R1,#12*8]
  298.  
  299.     TEQP PC,#USR_mode                  ; into user mode
  300.     MOV R0,R0
  301.  
  302.     MOV fp,#0                          ; no frame pointer
  303.         MOV R0,R4                          ; get the thread manager into "this" pointer
  304.         BL context_switch__13ThreadManagerFv         ; switch to another thread
  305.  
  306.         SWI OS_EnterOS                     ; back to supervisor mode
  307.         MOV R0,R0
  308.  
  309. ; now reload the registers from the save area
  310.  
  311.         LDR R1,thread_callback_regs
  312.         ADD R1,R1,#16*4
  313.         LDFE F0,[R1,#0]
  314.         LDFE F1,[R1,#12]
  315.         LDFE F2,[R1,#12*2]
  316.         LDFE F3,[R1,#12*3]
  317.         LDFE F4,[R1,#12*4]
  318.         LDFE F5,[R1,#12*5]
  319.         LDFE F6,[R1,#12*6]
  320.         LDFE F7,[R1,#12*7]
  321.     LDR R0,[R1,#12*8]
  322.     WFS R0                             ; write floating status
  323.  
  324.     MOV R0,#0
  325.     STR R0,thread_worksemaphore        ; enable the interrupts
  326.     SUB R14,R1,#16*4                   ; get address of USR mode integer registers
  327.     LDMIA R14,{R0-R14}^                ; load USR mode regs
  328.     MOV R0,R0
  329.     TEQP PC,#Int_bit+SVC_mode          ; disable ints
  330.     MOV R0,R0
  331.     LDR R14,[R14,#15*4]                ; load the old PC value
  332.     MOVS PC,R14                        ; return
  333.  
  334. ; entry:
  335. ;   R0 = save area
  336.  
  337. .thread_init_save_area
  338.         EXPORT thread_init_save_area
  339.         STMFD SP!,{R0,R1,link}
  340.         ADD R1,R0,#16*4
  341.         STFE F0,[R1,#0]
  342.         STFE F1,[R1,#12]
  343.         STFE F2,[R1,#12*2]
  344.         STFE F3,[R1,#12*3]
  345.         STFE F4,[R1,#12*4]
  346.         STFE F5,[R1,#12*5]
  347.         STFE F6,[R1,#12*6]
  348.         STFE F7,[R1,#12*7]
  349.     RFS R0                             ; read floating status
  350.     STR R0,[R1,#12*8]
  351.         LDMFD SP!,{R0,R1,PC}^
  352.  
  353.  
  354. ;
  355. ; claim the functions that modify the heap.
  356. ;
  357.  
  358. ; this claims the following functions:
  359. ;   malloc
  360. ;   free
  361. ;   calloc
  362. ;   realloc
  363.  
  364. ; and makes sure that the threads are diabled on each call
  365.  
  366.  
  367. .claimed_malloc
  368.     DCD 0
  369.  
  370. .my_malloc
  371.     STMFD SP!,{R4-R5,link}
  372.     MOV R4,R0
  373.     BL int_state
  374.     MOV R5,R0
  375.     BL thread_disable_ints
  376.     MOV R0,R4
  377.     MOV R14,PC
  378.     LDR PC,claimed_malloc
  379.     MOV R4,R0
  380.     CMP R5,#0
  381.     BLEQ thread_enable_ints
  382.     MOV R0,R4
  383.     LDMFD SP!,{R4-R5,PC}^
  384.  
  385. .claimed_free
  386.     DCD 0
  387.  
  388. .my_free
  389.     STMFD SP!,{R4-R5,link}
  390.     MOV R4,R0
  391.     BL int_state
  392.     MOV R5,R0
  393.     BL thread_disable_ints
  394.     MOV R0,R4
  395.     MOV R14,PC
  396.     LDR PC,claimed_free
  397.     MOV R4,R0
  398.     CMP R5,#0
  399.     BLEQ thread_enable_ints
  400.     MOV R0,R4
  401.     LDMFD SP!,{R4-R5,PC}^
  402.  
  403. .claimed_calloc
  404.     DCD 0
  405.  
  406. .my_calloc
  407.     STMFD SP!,{R4-R5,link}
  408.     MOV R4,R0
  409.     BL int_state
  410.     MOV R5,R0
  411.     BL thread_disable_ints
  412.     MOV R0,R4
  413.     MOV R14,PC
  414.     LDR PC,claimed_calloc
  415.     MOV R4,R0
  416.     CMP R5,#0
  417.     BLEQ thread_enable_ints
  418.     MOV R0,R4
  419.     LDMFD SP!,{R4-R5,PC}^
  420.  
  421. .claimed_realloc
  422.     DCD 0
  423.  
  424. .my_realloc
  425.     STMFD SP!,{R4-R5,link}
  426.     MOV R4,R0
  427.     BL int_state
  428.     MOV R5,R0
  429.     BL thread_disable_ints
  430.     MOV R0,R4
  431.     MOV R14,PC
  432.     LDR PC,claimed_realloc
  433.     MOV R4,R0
  434.     CMP R5,#0
  435.     BLEQ thread_enable_ints
  436.     MOV R0,R4
  437.     LDMFD SP!,{R4-R5,PC}^
  438.  
  439.  
  440.     IMPORT malloc
  441.     IMPORT free
  442.     IMPORT realloc
  443.     IMPORT calloc
  444.  
  445. .malloc_addr
  446.     DCD malloc
  447. .free_addr
  448.     DCD free
  449. .realloc_addr
  450.     DCD realloc
  451. .calloc_addr
  452.     DCD calloc
  453.  
  454. .claim_heap_modifiers
  455.         STMFD SP!,{link}
  456.         LDR R0,malloc_addr                  ; get address of malloc
  457.         ADR R1,claimed_malloc
  458.         ADR R2,my_malloc
  459.         BL claim_vector
  460.         LDR R0,free_addr                  ; get address of free
  461.         ADR R1,claimed_free
  462.         ADR R2,my_free
  463.         BL claim_vector
  464.         LDR R0,calloc_addr                  ; get address of calloc
  465.         ADR R1,claimed_calloc
  466.         ADR R2,my_calloc
  467.         BL claim_vector
  468.         LDR R0,realloc_addr                  ; get address of realloc
  469.         ADR R1,claimed_realloc
  470.         ADR R2,my_realloc
  471.         BL claim_vector
  472.     LDMFD SP!,{PC}^
  473.  
  474. ;
  475. ; claim a vector
  476. ;
  477.  
  478. ; entry:
  479. ;   R0 = address of vector to claim
  480. ;   R1 = address of word to hold old vector address
  481. ;   R2 = new vector address
  482.  
  483. .claim_vector
  484.     STMFD SP!,{R0-R3,link}
  485.     MOV R3,R0
  486.         LDR R0,[R3,#0]                      ; get B instruction
  487.     BIC R0,R0,#0xff000000               ; offset in words
  488.     MOV R0,R0,LSL #2                    ; offset in bytes
  489.     ADD R0,R0,R3                        ; add to malloc address
  490.     ADD R0,R0,#8                        ; add for  pipelining
  491.     STR R0,[R1,#0]                      ; store in old place
  492.     SUB R0,R2,R3                        ; calc offset from branch to routine
  493.     SUB R0,R0,#8                        ; remove pipelining
  494.     MOV R0,R0,LSR #2                    ; in words
  495.     ORR R0,R0,#0xEA000000               ; make branch
  496.     STR R0,[R3,#0]                      ; store in vector position
  497.     LDMFD SP!,{R0-R3,PC}^
  498.  
  499.  
  500. #pragma endasm
  501.