instruction_helpers.rs 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. macro_rules! SAFE_READ_WRITE8 {
  2. ($value:ident, $addr:expr, $instruction:expr) => {{
  3. use cpu::cpu::translate_address_write_and_can_skip_dirty;
  4. use cpu::memory;
  5. use page::Page;
  6. let (phys_addr, can_skip_dirty_page) =
  7. return_on_pagefault!(translate_address_write_and_can_skip_dirty($addr));
  8. let $value = memory::read8(phys_addr);
  9. let value = $instruction;
  10. if memory::in_mapped_range(phys_addr) {
  11. memory::mmap_write8(phys_addr, value);
  12. }
  13. else {
  14. if !can_skip_dirty_page {
  15. ::jit::jit_dirty_page(::jit::get_jit_state(), Page::page_of(phys_addr));
  16. }
  17. else {
  18. dbg_assert!(!::jit::jit_page_has_code(Page::page_of(phys_addr as u32)));
  19. }
  20. memory::write8_no_mmap_or_dirty_check(phys_addr, value);
  21. }
  22. }};
  23. }
  24. macro_rules! SAFE_READ_WRITE16 {
  25. ($value:ident, $addr:expr, $instruction:expr) => {{
  26. use cpu::cpu::{
  27. translate_address_write_and_can_skip_dirty, virt_boundary_read16, virt_boundary_write16,
  28. };
  29. use cpu::memory;
  30. use page::Page;
  31. let (phys_addr, can_skip_dirty_page) =
  32. return_on_pagefault!(translate_address_write_and_can_skip_dirty($addr));
  33. if phys_addr & 0xFFF == 0xFFF {
  34. let phys_addr_high = return_on_pagefault!(translate_address_write($addr + 1));
  35. let $value = virt_boundary_read16(phys_addr, phys_addr_high);
  36. virt_boundary_write16(phys_addr, phys_addr_high, $instruction);
  37. }
  38. else {
  39. let $value = memory::read16(phys_addr);
  40. let value = $instruction;
  41. if memory::in_mapped_range(phys_addr) {
  42. memory::mmap_write16(phys_addr, value);
  43. }
  44. else {
  45. if !can_skip_dirty_page {
  46. ::jit::jit_dirty_page(::jit::get_jit_state(), Page::page_of(phys_addr));
  47. }
  48. else {
  49. dbg_assert!(!::jit::jit_page_has_code(Page::page_of(phys_addr as u32)));
  50. }
  51. memory::write16_no_mmap_or_dirty_check(phys_addr, value);
  52. };
  53. }
  54. }};
  55. }
  56. macro_rules! SAFE_READ_WRITE32 {
  57. ($value:ident, $addr:expr, $instruction:expr) => {{
  58. use cpu::cpu::{
  59. translate_address_write_and_can_skip_dirty, virt_boundary_read32s,
  60. virt_boundary_write32,
  61. };
  62. use cpu::memory;
  63. use page::Page;
  64. let (phys_addr, can_skip_dirty_page) =
  65. return_on_pagefault!(translate_address_write_and_can_skip_dirty($addr));
  66. if phys_addr & 0xFFF >= 0xFFD {
  67. let phys_addr_high = return_on_pagefault!(translate_address_write($addr + 3 & !3));
  68. let phys_addr_high = phys_addr_high | ($addr as u32) + 3 & 3;
  69. let $value = virt_boundary_read32s(phys_addr, phys_addr_high);
  70. virt_boundary_write32(phys_addr, phys_addr_high, $instruction);
  71. }
  72. else {
  73. let $value = memory::read32s(phys_addr);
  74. let value = $instruction;
  75. if memory::in_mapped_range(phys_addr) {
  76. memory::mmap_write32(phys_addr, value);
  77. }
  78. else {
  79. if !can_skip_dirty_page {
  80. ::jit::jit_dirty_page(::jit::get_jit_state(), Page::page_of(phys_addr));
  81. }
  82. else {
  83. dbg_assert!(!::jit::jit_page_has_code(Page::page_of(phys_addr as u32)));
  84. }
  85. memory::write32_no_mmap_or_dirty_check(phys_addr, value);
  86. };
  87. }
  88. }};
  89. }