mcd_arm.s 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. @*
  2. @* CPU scheduling code
  3. @* (C) notaz, 2007-2008
  4. @*
  5. @* This work is licensed under the terms of MAME license.
  6. @* See COPYING file in the top-level directory.
  7. @*
  8. @ SekRunPS runs PicoCpuCM68k and PicoCpuCS68k interleaved in steps of PS_STEP_M68K
  9. @ cycles. This is done without calling CycloneRun and jumping directly to
  10. @ Cyclone code to avoid pushing/popping all the registers every time.
  11. .equiv PS_STEP_M68K, ((488<<16)/20) @ ~24
  12. @ .extern is ignored by gas, we add these here just to see what we depend on.
  13. .extern CycloneJumpTab
  14. .extern CycloneDoInterrupt
  15. .extern PicoCpuCM68k
  16. .extern PicoCpuCS68k
  17. .extern SekCycleAim
  18. .extern SekCycleCnt
  19. .extern SekCycleAimS68k
  20. .extern SekCycleCntS68k
  21. .text
  22. .align 4
  23. .global SekRunPS @ cyc_m68k, cyc_s68k
  24. SekRunPS:
  25. stmfd sp!, {r4-r8,r10,r11,lr}
  26. sub sp, sp, #2*4 @ sp[0] = main_cycle_cnt, sp[4] = run_cycle_cnt
  27. @ override CycloneEnd for both contexts
  28. ldr r7, =PicoCpuCM68k
  29. ldr lr, =PicoCpuCS68k
  30. ldr r2, =CycloneEnd_M68k
  31. ldr r3, =CycloneEnd_S68k
  32. str r2, [r7,#0x98]
  33. str r3, [lr,#0x98]
  34. @ update aims
  35. ldr r8, =SekCycleAim
  36. ldr r10,=SekCycleAimS68k
  37. ldr r2, [r8]
  38. ldr r3, [r10]
  39. add r2, r2, r0
  40. add r3, r3, r1
  41. str r2, [r8]
  42. str r3, [r10]
  43. ldr r6, =CycloneJumpTab
  44. ldr r1, =SekCycleCnt
  45. ldr r0, =((488<<16)-PS_STEP_M68K)
  46. str r6, [r7,#0x54]
  47. str r6, [lr,#0x54] @ make copies to avoid literal pools
  48. @ schedule m68k for the first time..
  49. ldr r1, [r1]
  50. str r0, [sp] @ main target 'left cycle' counter
  51. sub r1, r2, r1
  52. subs r5, r1, r0, asr #16
  53. ble schedule_s68k @ m68k has not enough cycles
  54. str r5, [sp,#4] @ run_cycle_cnt
  55. b CycloneRunLocal
  56. CycloneEnd_M68k:
  57. ldr r3, =SekCycleCnt
  58. ldr r0, [sp,#4] @ run_cycle_cnt
  59. ldr r1, [r3]
  60. str r4, [r7,#0x40] ;@ Save Current PC + Memory Base
  61. strb r10,[r7,#0x46] ;@ Save Flags (NZCV)
  62. sub r0, r0, r5 @ subtract leftover cycles (which should be negative)
  63. add r0, r0, r1
  64. str r0, [r3]
  65. schedule_s68k:
  66. ldr r8, =SekCycleCntS68k
  67. ldr r10,=SekCycleAimS68k
  68. ldr r3, [sp]
  69. ldr r8, [r8]
  70. ldr r10,[r10]
  71. sub r0, r10, r8
  72. mov r2, r3
  73. add r3, r3, r2, asr #1
  74. add r3, r3, r2, asr #3 @ cycn_s68k = (cycn + cycn/2 + cycn/8)
  75. subs r5, r0, r3, asr #16
  76. ble schedule_m68k @ s68k has not enough cycles
  77. ldr r7, =PicoCpuCS68k
  78. str r5, [sp,#4] @ run_cycle_cnt
  79. b CycloneRunLocal
  80. CycloneEnd_S68k:
  81. ldr r3, =SekCycleCntS68k
  82. ldr r0, [sp,#4] @ run_cycle_cnt
  83. ldr r1, [r3]
  84. str r4, [r7,#0x40] ;@ Save Current PC + Memory Base
  85. strb r10,[r7,#0x46] ;@ Save Flags (NZCV)
  86. sub r0, r0, r5 @ subtract leftover cycles (should be negative)
  87. add r0, r0, r1
  88. str r0, [r3]
  89. schedule_m68k:
  90. ldr r1, =PS_STEP_M68K
  91. ldr r3, [sp] @ main_cycle_cnt
  92. ldr r8, =SekCycleCnt
  93. ldr r10,=SekCycleAim
  94. subs r3, r3, r1
  95. bmi SekRunPS_end
  96. ldr r8, [r8]
  97. ldr r10,[r10]
  98. str r3, [sp] @ update main_cycle_cnt
  99. sub r0, r10, r8
  100. subs r5, r0, r3, asr #16
  101. ble schedule_s68k @ m68k has not enough cycles
  102. ldr r7, =PicoCpuCM68k
  103. str r5, [sp,#4] @ run_cycle_cnt
  104. b CycloneRunLocal
  105. SekRunPS_end:
  106. ldr r7, =PicoCpuCM68k
  107. ldr lr, =PicoCpuCS68k
  108. mov r0, #0
  109. str r0, [r7,#0x98] @ remove CycloneEnd handler
  110. str r0, [lr,#0x98]
  111. @ return
  112. add sp, sp, #2*4
  113. ldmfd sp!, {r4-r8,r10,r11,pc}
  114. CycloneRunLocal:
  115. ;@ r0-3 = Temporary registers
  116. ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base
  117. ;@ r5 = Cycles
  118. ;@ r6 = Opcode Jump table
  119. ;@ r7 = Pointer to Cpu Context
  120. ;@ r8 = Current Opcode
  121. ldrb r10,[r7,#0x46];@ r10 = Flags (NZCV)
  122. ldr r1,[r7,#0x44] ;@ get SR high and IRQ level
  123. orr r10,r10,r10,lsl #28 ;@ r10 = Flags 0xf0000000, cpsr format
  124. ;@ CheckInterrupt:
  125. movs r0,r1,lsr #24 ;@ Get IRQ level
  126. beq NoIntsLocal
  127. cmp r0,#6 ;@ irq>6 ?
  128. andle r1,r1,#7 ;@ Get interrupt mask
  129. cmple r0,r1 ;@ irq<=6: Is irq<=mask ?
  130. bgt CycloneDoInterrupt
  131. NoIntsLocal:
  132. ;@ Check if our processor is in special state
  133. ;@ and jump to opcode handler if not
  134. ldr r0,[r7,#0x58] ;@ state_flags
  135. ldrh r8,[r4],#2 ;@ Fetch first opcode
  136. tst r0,#0x03 ;@ special state?
  137. andeq r10,r10,#0xf0000000
  138. ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler
  139. CycloneSpecial2:
  140. tst r0,#2 ;@ tracing?
  141. bne CycloneDoTrace
  142. ;@ stopped or halted
  143. sub r4,r4,#2
  144. ldr r1,[r7,#0x98]
  145. mov r5,#0
  146. bx r1
  147. @ vim:filetype=armasm