1 // license:BSD-3-Clause 2 // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz 3 /* ARM7 core helper Macros / Functions */ 4 5 /* Macros that need to be defined according to the cpu implementation specific need */ 6 #define ARM7REG(reg) m_r[reg] 7 #define ARM7_ICOUNT m_icount 8 9 10 /*************** 11 * helper funcs 12 ***************/ 13 14 // TODO LD: 15 // - SIGN_BITS_DIFFER = THUMB_SIGN_BITS_DIFFER 16 // - do while (0) 17 // - HandleALUAddFlags = HandleThumbALUAddFlags except for PC incr 18 // - HandleALUSubFlags = HandleThumbALUSubFlags except for PC incr 19 20 #define IsNeg(i) ((i) >> 31) 21 #define IsPos(i) ((~(i)) >> 31) 22 23 /* Set NZCV flags for ADDS / SUBS */ 24 #define HandleALUAddFlags(rd, rn, op2) \ 25 if (insn & INSN_S) \ 26 set_cpsr(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ 27 | (((!SIGN_BITS_DIFFER(rn, op2)) && SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ 28 | (((IsNeg(rn) & IsNeg(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsNeg(op2) & IsPos(rd))) ? C_MASK : 0) \ 29 | HandleALUNZFlags(rd))); \ 30 R15 += 4; 31 32 #define HandleThumbALUAddFlags(rd, rn, op2) \ 33 set_cpsr(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ 34 | (((!THUMB_SIGN_BITS_DIFFER(rn, op2)) && THUMB_SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ 35 | (((~(rn)) < (op2)) << C_BIT) \ 36 | HandleALUNZFlags(rd))); \ 37 R15 += 2; 38 39 #define DRCHandleThumbALUAddFlags(rd, rn, op2) \ 40 UML_AND(block, DRC_CPSR, DRC_CPSR, ~(N_MASK | Z_MASK | V_MASK | C_MASK)); \ 41 DRCHandleALUNZFlags(rd); \ 42 UML_XOR(block, uml::I1, rn, ~0); \ 43 UML_CMP(block, uml::I1, op2); \ 44 UML_MOVc(block, uml::COND_B, uml::I1, C_BIT); \ 45 UML_MOVc(block, uml::COND_AE, uml::I1, 0); \ 46 UML_OR(block, uml::I0, uml::I0, uml::I1); \ 47 UML_XOR(block, uml::I1, rn, op2); \ 48 UML_XOR(block, uml::I2, rn, rd); \ 49 UML_AND(block, uml::I1, uml::I1, uml::I2); \ 50 UML_TEST(block, uml::I1, 1 << 31); \ 51 UML_MOVc(block, uml::COND_NZ, uml::I1, V_BIT); \ 52 UML_MOVc(block, uml::COND_Z, uml::I1, 0); \ 53 UML_OR(block, uml::I0, uml::I0, uml::I1); \ 54 UML_OR(block, DRC_CPSR, DRC_CPSR, uml::I0); \ 55 UML_ADD(block, DRC_PC, DRC_PC, 2); 56 57 #define HandleALUSubFlags(rd, rn, op2) \ 58 if (insn & INSN_S) \ 59 set_cpsr(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ 60 | ((SIGN_BITS_DIFFER(rn, op2) && SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ 61 | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \ 62 | HandleALUNZFlags(rd))); \ 63 R15 += 4; 64 65 #define HandleThumbALUSubFlags(rd, rn, op2) \ 66 set_cpsr(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ 67 | ((THUMB_SIGN_BITS_DIFFER(rn, op2) && THUMB_SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ 68 | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \ 69 | HandleALUNZFlags(rd))); \ 70 R15 += 2; 71 72 #define DRCHandleThumbALUSubFlags(rd, rn, op2) \ 73 UML_AND(block, DRC_CPSR, DRC_CPSR, ~(N_MASK | Z_MASK | V_MASK | C_MASK)); \ 74 DRCHandleALUNZFlags(rd); \ 75 UML_XOR(block, uml::I1, rn, op2); \ 76 UML_XOR(block, uml::I2, rn, rd); \ 77 UML_AND(block, uml::I1, uml::I1, uml::I2); \ 78 UML_TEST(block, uml::I1, 1 << 31); \ 79 UML_MOVc(block, uml::COND_NZ, uml::I1, V_BIT); \ 80 UML_MOVc(block, uml::COND_Z, uml::I1, 0); \ 81 UML_OR(block, uml::I0, uml::I0, uml::I1); \ 82 UML_OR(block, DRC_CPSR, DRC_CPSR, uml::I0); \ 83 UML_AND(block, uml::I0, rd, 1 << 31); \ 84 UML_AND(block, uml::I1, op2, 1 << 31); \ 85 UML_AND(block, uml::I2, rn, 1 << 31); \ 86 UML_XOR(block, uml::I2, uml::I2, ~0); \ 87 UML_AND(block, uml::I1, uml::I1, uml::I2); \ 88 UML_AND(block, uml::I2, uml::I2, uml::I0); \ 89 UML_OR(block, uml::I1, uml::I1, uml::I2); \ 90 UML_AND(block, uml::I2, op2, 1 << 31); \ 91 UML_AND(block, uml::I2, uml::I2, uml::I0); \ 92 UML_OR(block, uml::I1, uml::I1, uml::I2); \ 93 UML_TEST(block, uml::I1, 1 << 31); \ 94 UML_MOVc(block, uml::COND_NZ, uml::I0, C_MASK); \ 95 UML_MOVc(block, uml::COND_Z, uml::I0, 0); \ 96 UML_OR(block, DRC_CPSR, DRC_CPSR, uml::I0); \ 97 UML_ADD(block, DRC_PC, DRC_PC, 2); 98 99 /* Set NZC flags for logical operations. */ 100 101 // This macro (which I didn't write) - doesn't make it obvious that the SIGN BIT = 31, just as the N Bit does, 102 // therefore, N is set by default 103 #define HandleALUNZFlags(rd) \ 104 (((rd) & SIGN_BIT) | ((!(rd)) << Z_BIT)) 105 106 #define DRCHandleALUNZFlags(rd) \ 107 UML_AND(block, uml::I0, rd, SIGN_BIT); \ 108 UML_CMP(block, rd, 0); \ 109 UML_MOVc(block, uml::COND_E, uml::I1, 1); \ 110 UML_MOVc(block, uml::COND_NE, uml::I1, 0); \ 111 UML_ROLINS(block, uml::I0, uml::I1, Z_BIT, 1 << Z_BIT); 112 113 // Long ALU Functions use bit 63 114 #define HandleLongALUNZFlags(rd) \ 115 ((((rd) & ((uint64_t)1 << 63)) >> 32) | ((!(rd)) << Z_BIT)) 116 117 #define HandleALULogicalFlags(rd, sc) \ 118 if (insn & INSN_S) \ 119 set_cpsr(((GET_CPSR & ~(N_MASK | Z_MASK | C_MASK)) \ 120 | HandleALUNZFlags(rd) \ 121 | (((sc) != 0) << C_BIT))); \ 122 R15 += 4; 123 124 #define DRC_RD uml::mem(&GetRegister(rd)) 125 #define DRC_RS uml::mem(&GetRegister(rs)) 126 #define DRC_CPSR uml::mem(&GET_CPSR) 127 #define DRC_PC uml::mem(&R15) 128 #define DRC_REG(i) uml::mem(&m_r[(i)]) 129 130 #define DRCHandleALULogicalFlags(rd, sc) \ 131 if (insn & INSN_S) \ 132 { \ 133 UML_AND(block, DRC_CPSR, DRC_CPSR, ~(N_MASK | Z_MASK | C_MASK); \ 134 DRCHandleALUNZFlags(rd); \ 135 UML_TEST(block, sc, ~0); \ 136 UML_MOVc(block, uml::COND_Z, uml::I1, C_BIT); \ 137 UML_MOVc(block, uml::COND_NZ, uml::I1, 0); \ 138 UML_OR(block, uml::I0, uml::I0, uml::I1); \ 139 UML_OR(block, DRC_CPSR, DRC_CPSR, uml::I0); \ 140 } \ 141 UML_ADD(block, DRC_PC, DRC_PC, 4); 142 143 144 // used to be functions, but no longer a need, so we'll use define for better speed. 145 #define GetRegister(rIndex) m_r[m_reg_group[rIndex]] 146 #define SetRegister(rIndex, value) m_r[m_reg_group[rIndex]] = value 147 148 #define GetModeRegister(mode, rIndex) m_r[sRegisterTable[mode][rIndex]] 149 #define SetModeRegister(mode, rIndex, value) m_r[sRegisterTable[mode][rIndex]] = value 150 151 152 /* Macros that can be re-defined for custom cpu implementations - The core expects these to be defined */ 153 /* In this case, we are using the default arm7 handlers (supplied by the core) 154 - but simply changes these and define your own if needed for cpu implementation specific needs */ 155 #define READ8(addr) arm7_cpu_read8(addr) 156 #define WRITE8(addr,data) arm7_cpu_write8(addr,data) 157 #define READ16(addr) arm7_cpu_read16(addr) 158 #define WRITE16(addr,data) arm7_cpu_write16(addr,data) 159 #define READ32(addr) arm7_cpu_read32(addr) 160 #define WRITE32(addr,data) arm7_cpu_write32(addr,data) 161 #define PTR_READ32 &arm7_cpu_read32 162 #define PTR_WRITE32 &arm7_cpu_write32 163 164 #define LSL(v, s) ((v) << (s)) 165 #define LSR(v, s) ((v) >> (s)) 166 #define ROL(v, s) (LSL((v), (s)) | (LSR((v), 32u - (s)))) 167 #define ROR(v, s) (LSR((v), (s)) | (LSL((v), 32u - (s)))) 168