_fline_internal_emulator_4_r.s 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. | Most of this code was contributed by ExtendeD.
  2. .xdef __fline_handle_rom_call
  3. .section _st10038
  4. __fline_handle_rom_call:
  5. .if 0
  6. | Put the value of %d2 into %a0 and restore it later,
  7. | since no known ROM call takes an address register parameter,
  8. | but some (including _bcd_math) take arbitrary data register parameters.
  9. move.l %d2,%a0
  10. .endif
  11. | Ignore the saved value of %a1, for the same reason.
  12. addq.l #4,%sp
  13. move.w (%sp)+,%d2
  14. addq.l #4,%sp
  15. | %sp (the supervisor stack pointer) is the same as it was before the
  16. | interrupt was called.
  17. | Now we restore the status register, which usually gets back to user mode
  18. | (so %sp points to the the user stack from now on). Anyway, even if we were
  19. | in supervisor mode before (i.e. in an interrupt handler), the situation
  20. | will now be the same as before the call.
  21. move.w %d2,%sr
  22. | Get the word at the address in %a1 (the return address). It contains
  23. | _F_LINE+idx.
  24. | Add 2 to %a1, so we will return to the next instruction instead of running
  25. | into an endless loop.
  26. move.w (%a1)+,%d2
  27. | Push the return address on the user stack (it will be used by the 'rts' at
  28. | the end of the function).
  29. pea.l (%a1)
  30. | Get the address of the jump table.
  31. move.l 0xC8,%a1
  32. | Get the ROM call index. We could subtract _F_LINE from %d2, but this is
  33. | faster.
  34. and.w #0x7FF,%d2
  35. | Multiply by 4 (size of a pointer).
  36. lsl.w #2,%d2
  37. | Calculate the address of the ROM Call in %a0.
  38. move.l (%a1,%d2.w),%a1
  39. .if 0
  40. | Restore the value of %d2.
  41. move.l %a0,%d2
  42. .endif
  43. | Jump to the ROM function. We can do it this way since we are in the mode in
  44. | which the function has to be executed.
  45. jmp (%a1)