| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | static void emit_tab(ASMState *as, PPCIns pi, Reg rt, Reg ra, Reg rb) |
| 9 | { |
| 10 | *--as->mcp = pi | PPCF_T(rt) | PPCF_A(ra) | PPCF_B(rb); |
| 11 | } |
| 12 | |
| 13 | #define emit_asb(as, pi, ra, rs, rb) emit_tab(as, (pi), (rs), (ra), (rb)) |
| 14 | #define emit_as(as, pi, ra, rs) emit_tab(as, (pi), (rs), (ra), 0) |
| 15 | #define emit_ab(as, pi, ra, rb) emit_tab(as, (pi), 0, (ra), (rb)) |
| 16 | |
| 17 | static void emit_tai(ASMState *as, PPCIns pi, Reg rt, Reg ra, int32_t i) |
| 18 | { |
| 19 | *--as->mcp = pi | PPCF_T(rt) | PPCF_A(ra) | (i & 0xffff); |
| 20 | } |
| 21 | |
| 22 | #define emit_ti(as, pi, rt, i) emit_tai(as, (pi), (rt), 0, (i)) |
| 23 | #define emit_ai(as, pi, ra, i) emit_tai(as, (pi), 0, (ra), (i)) |
| 24 | #define emit_asi(as, pi, ra, rs, i) emit_tai(as, (pi), (rs), (ra), (i)) |
| 25 | |
| 26 | #define emit_fab(as, pi, rf, ra, rb) \ |
| 27 | emit_tab(as, (pi), (rf)&31, (ra)&31, (rb)&31) |
| 28 | #define emit_fb(as, pi, rf, rb) emit_tab(as, (pi), (rf)&31, 0, (rb)&31) |
| 29 | #define emit_fac(as, pi, rf, ra, rc) \ |
| 30 | emit_tab(as, (pi) | PPCF_C((rc) & 31), (rf)&31, (ra)&31, 0) |
| 31 | #define emit_facb(as, pi, rf, ra, rc, rb) \ |
| 32 | emit_tab(as, (pi) | PPCF_C((rc) & 31), (rf)&31, (ra)&31, (rb)&31) |
| 33 | #define emit_fai(as, pi, rf, ra, i) emit_tai(as, (pi), (rf)&31, (ra), (i)) |
| 34 | |
| 35 | static void emit_rot(ASMState *as, PPCIns pi, Reg ra, Reg rs, |
| 36 | int32_t n, int32_t b, int32_t e) |
| 37 | { |
| 38 | *--as->mcp = pi | PPCF_T(rs) | PPCF_A(ra) | PPCF_B(n) | |
| 39 | PPCF_MB(b) | PPCF_ME(e); |
| 40 | } |
| 41 | |
| 42 | static void emit_slwi(ASMState *as, Reg ra, Reg rs, int32_t n) |
| 43 | { |
| 44 | lua_assert(n >= 0 && n < 32); |
| 45 | emit_rot(as, PPCI_RLWINM, ra, rs, n, 0, 31-n); |
| 46 | } |
| 47 | |
| 48 | static void emit_rotlwi(ASMState *as, Reg ra, Reg rs, int32_t n) |
| 49 | { |
| 50 | lua_assert(n >= 0 && n < 32); |
| 51 | emit_rot(as, PPCI_RLWINM, ra, rs, n, 0, 31); |
| 52 | } |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | #define emit_canremat(ref) ((ref) <= REF_BASE) |
| 58 | |
| 59 | |
| 60 | static int emit_kdelta1(ASMState *as, Reg t, int32_t i) |
| 61 | { |
| 62 | RegSet work = ~as->freeset & RSET_GPR; |
| 63 | while (work) { |
| 64 | Reg r = rset_picktop(work); |
| 65 | IRRef ref = regcost_ref(as->cost[r]); |
| 66 | lua_assert(r != t); |
| 67 | if (ref < ASMREF_L) { |
| 68 | int32_t delta = i - (ra_iskref(ref) ? ra_krefk(as, ref) : IR(ref)->i); |
| 69 | if (checki16(delta)) { |
| 70 | emit_tai(as, PPCI_ADDI, t, r, delta); |
| 71 | return 1; |
| 72 | } |
| 73 | } |
| 74 | rset_clear(work, r); |
| 75 | } |
| 76 | return 0; |
| 77 | } |
| 78 | |
| 79 | |
| 80 | static void emit_loadi(ASMState *as, Reg r, int32_t i) |
| 81 | { |
| 82 | if (checki16(i)) { |
| 83 | emit_ti(as, PPCI_LI, r, i); |
| 84 | } else { |
| 85 | if ((i & 0xffff)) { |
| 86 | int32_t jgl = i32ptr(J2G(as->J)); |
| 87 | if ((uint32_t)(i-jgl) < 65536) { |
| 88 | emit_tai(as, PPCI_ADDI, r, RID_JGL, i-jgl-32768); |
| 89 | return; |
| 90 | } else if (emit_kdelta1(as, r, i)) { |
| 91 | return; |
| 92 | } |
| 93 | emit_asi(as, PPCI_ORI, r, r, i); |
| 94 | } |
| 95 | emit_ti(as, PPCI_LIS, r, (i >> 16)); |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | #define emit_loada(as, r, addr) emit_loadi(as, (r), i32ptr((addr))) |
| 100 | |
| 101 | static Reg ra_allock(ASMState *as, int32_t k, RegSet allow); |
| 102 | |
| 103 | |
| 104 | static void emit_lsptr(ASMState *as, PPCIns pi, Reg r, void *p, RegSet allow) |
| 105 | { |
| 106 | int32_t jgl = i32ptr(J2G(as->J)); |
| 107 | int32_t i = i32ptr(p); |
| 108 | Reg base; |
| 109 | if ((uint32_t)(i-jgl) < 65536) { |
| 110 | i = i-jgl-32768; |
| 111 | base = RID_JGL; |
| 112 | } else { |
| 113 | base = ra_allock(as, i-(int16_t)i, allow); |
| 114 | } |
| 115 | emit_tai(as, pi, r, base, i); |
| 116 | } |
| 117 | |
| 118 | #define emit_loadn(as, r, tv) \ |
| 119 | emit_lsptr(as, PPCI_LFD, ((r) & 31), (void *)(tv), RSET_GPR) |
| 120 | |
| 121 | |
| 122 | static void emit_lsglptr(ASMState *as, PPCIns pi, Reg r, int32_t ofs) |
| 123 | { |
| 124 | emit_tai(as, pi, r, RID_JGL, ofs-32768); |
| 125 | } |
| 126 | |
| 127 | #define emit_getgl(as, r, field) \ |
| 128 | emit_lsglptr(as, PPCI_LWZ, (r), (int32_t)offsetof(global_State, field)) |
| 129 | #define emit_setgl(as, r, field) \ |
| 130 | emit_lsglptr(as, PPCI_STW, (r), (int32_t)offsetof(global_State, field)) |
| 131 | |
| 132 | |
| 133 | #define emit_setvmstate(as, i) UNUSED(i) |
| 134 | |
| 135 | |
| 136 | |
| 137 | |
| 138 | typedef MCode *MCLabel; |
| 139 | |
| 140 | |
| 141 | #define emit_label(as) ((as)->mcp) |
| 142 | |
| 143 | static void emit_condbranch(ASMState *as, PPCIns pi, PPCCC cc, MCode *target) |
| 144 | { |
| 145 | MCode *p = --as->mcp; |
| 146 | ptrdiff_t delta = (char *)target - (char *)p; |
| 147 | lua_assert(((delta + 0x8000) >> 16) == 0); |
| 148 | pi ^= (delta & 0x8000) * (PPCF_Y/0x8000); |
| 149 | *p = pi | PPCF_CC(cc) | ((uint32_t)delta & 0xffffu); |
| 150 | } |
| 151 | |
| 152 | static void emit_jmp(ASMState *as, MCode *target) |
| 153 | { |
| 154 | MCode *p = --as->mcp; |
| 155 | ptrdiff_t delta = (char *)target - (char *)p; |
| 156 | *p = PPCI_B | (delta & 0x03fffffcu); |
| 157 | } |
| 158 | |
| 159 | static void emit_call(ASMState *as, void *target) |
| 160 | { |
| 161 | MCode *p = --as->mcp; |
| 162 | ptrdiff_t delta = (char *)target - (char *)p; |
| 163 | if ((((delta>>2) + 0x00800000) >> 24) == 0) { |
| 164 | *p = PPCI_BL | (delta & 0x03fffffcu); |
| 165 | } else { |
| 166 | RegSet allow = RSET_GPR & ~RSET_RANGE(RID_R0, REGARG_LASTGPR+1); |
| 167 | Reg r = ra_allock(as, i32ptr(target), allow); |
| 168 | *p = PPCI_BCTRL; |
| 169 | p[-1] = PPCI_MTCTR | PPCF_T(r); |
| 170 | as->mcp = p-1; |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | |
| 175 | |
| 176 | #define emit_mr(as, dst, src) \ |
| 177 | emit_asb(as, PPCI_MR, (dst), (src), (src)) |
| 178 | |
| 179 | |
| 180 | static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src) |
| 181 | { |
| 182 | UNUSED(ir); |
| 183 | if (dst < RID_MAX_GPR) |
| 184 | emit_mr(as, dst, src); |
| 185 | else |
| 186 | emit_fb(as, PPCI_FMR, dst, src); |
| 187 | } |
| 188 | |
| 189 | |
| 190 | static void emit_spload(ASMState *as, IRIns *ir, Reg r, int32_t ofs) |
| 191 | { |
| 192 | if (r < RID_MAX_GPR) |
| 193 | emit_tai(as, PPCI_LWZ, r, RID_SP, ofs); |
| 194 | else |
| 195 | emit_fai(as, irt_isnum(ir->t) ? PPCI_LFD : PPCI_LFS, r, RID_SP, ofs); |
| 196 | } |
| 197 | |
| 198 | |
| 199 | static void emit_spstore(ASMState *as, IRIns *ir, Reg r, int32_t ofs) |
| 200 | { |
| 201 | if (r < RID_MAX_GPR) |
| 202 | emit_tai(as, PPCI_STW, r, RID_SP, ofs); |
| 203 | else |
| 204 | emit_fai(as, irt_isnum(ir->t) ? PPCI_STFD : PPCI_STFS, r, RID_SP, ofs); |
| 205 | } |
| 206 | |
| 207 | |
| 208 | static void emit_cmpi(ASMState *as, Reg r, int32_t k) |
| 209 | { |
| 210 | if (checki16(k)) { |
| 211 | emit_ai(as, PPCI_CMPWI, r, k); |
| 212 | } else if (checku16(k)) { |
| 213 | emit_ai(as, PPCI_CMPLWI, r, k); |
| 214 | } else { |
| 215 | emit_ai(as, PPCI_CMPLWI, RID_TMP, k); |
| 216 | emit_asi(as, PPCI_XORIS, RID_TMP, r, (k >> 16)); |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | |
| 221 | static void emit_addptr(ASMState *as, Reg r, int32_t ofs) |
| 222 | { |
| 223 | if (ofs) { |
| 224 | emit_tai(as, PPCI_ADDI, r, r, ofs); |
| 225 | if (!checki16(ofs)) |
| 226 | emit_tai(as, PPCI_ADDIS, r, r, (ofs + 32768) >> 16); |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | static void emit_spsub(ASMState *as, int32_t ofs) |
| 231 | { |
| 232 | if (ofs) { |
| 233 | emit_tai(as, PPCI_STWU, RID_TMP, RID_SP, -ofs); |
| 234 | emit_tai(as, PPCI_ADDI, RID_TMP, RID_SP, |
| 235 | CFRAME_SIZE + (as->parent ? as->parent->spadjust : 0)); |
| 236 | } |
| 237 | } |
| 238 | |