diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_emit_mips.h | 107 |
1 files changed, 93 insertions, 14 deletions
diff --git a/src/lj_emit_mips.h b/src/lj_emit_mips.h index 20ecb7a2..8a9ee24d 100644 --- a/src/lj_emit_mips.h +++ b/src/lj_emit_mips.h | |||
@@ -3,6 +3,28 @@ | |||
3 | ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h | 3 | ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #if LJ_64 | ||
7 | static intptr_t get_k64val(IRIns *ir) | ||
8 | { | ||
9 | if (ir->o == IR_KINT64) { | ||
10 | return (intptr_t)ir_kint64(ir)->u64; | ||
11 | } else if (ir->o == IR_KGC) { | ||
12 | return (intptr_t)ir_kgc(ir); | ||
13 | } else if (ir->o == IR_KPTR || ir->o == IR_KKPTR) { | ||
14 | return (intptr_t)ir_kptr(ir); | ||
15 | } else { | ||
16 | lua_assert(ir->o == IR_KINT || ir->o == IR_KNULL); | ||
17 | return ir->i; /* Sign-extended. */ | ||
18 | } | ||
19 | } | ||
20 | #endif | ||
21 | |||
22 | #if LJ_64 | ||
23 | #define get_kval(ir) get_k64val(ir) | ||
24 | #else | ||
25 | #define get_kval(ir) ((ir)->i) | ||
26 | #endif | ||
27 | |||
6 | /* -- Emit basic instructions --------------------------------------------- */ | 28 | /* -- Emit basic instructions --------------------------------------------- */ |
7 | 29 | ||
8 | static void emit_dst(ASMState *as, MIPSIns mi, Reg rd, Reg rs, Reg rt) | 30 | static void emit_dst(ASMState *as, MIPSIns mi, Reg rd, Reg rs, Reg rt) |
@@ -35,7 +57,7 @@ static void emit_fgh(ASMState *as, MIPSIns mi, Reg rf, Reg rg, Reg rh) | |||
35 | 57 | ||
36 | static void emit_rotr(ASMState *as, Reg dest, Reg src, Reg tmp, uint32_t shift) | 58 | static void emit_rotr(ASMState *as, Reg dest, Reg src, Reg tmp, uint32_t shift) |
37 | { | 59 | { |
38 | if ((as->flags & JIT_F_MIPSXXR2)) { | 60 | if (LJ_64 || (as->flags & JIT_F_MIPSXXR2)) { |
39 | emit_dta(as, MIPSI_ROTR, dest, src, shift); | 61 | emit_dta(as, MIPSI_ROTR, dest, src, shift); |
40 | } else { | 62 | } else { |
41 | emit_dst(as, MIPSI_OR, dest, dest, tmp); | 63 | emit_dst(as, MIPSI_OR, dest, dest, tmp); |
@@ -44,13 +66,21 @@ static void emit_rotr(ASMState *as, Reg dest, Reg src, Reg tmp, uint32_t shift) | |||
44 | } | 66 | } |
45 | } | 67 | } |
46 | 68 | ||
69 | #if LJ_64 | ||
70 | static void emit_tsml(ASMState *as, MIPSIns mi, Reg rt, Reg rs, uint32_t msb, | ||
71 | uint32_t lsb) | ||
72 | { | ||
73 | *--as->mcp = mi | MIPSF_T(rt) | MIPSF_S(rs) | MIPSF_M(msb) | MIPSF_L(lsb); | ||
74 | } | ||
75 | #endif | ||
76 | |||
47 | /* -- Emit loads/stores --------------------------------------------------- */ | 77 | /* -- Emit loads/stores --------------------------------------------------- */ |
48 | 78 | ||
49 | /* Prefer rematerialization of BASE/L from global_State over spills. */ | 79 | /* Prefer rematerialization of BASE/L from global_State over spills. */ |
50 | #define emit_canremat(ref) ((ref) <= REF_BASE) | 80 | #define emit_canremat(ref) ((ref) <= REF_BASE) |
51 | 81 | ||
52 | /* Try to find a one step delta relative to another constant. */ | 82 | /* Try to find a one step delta relative to another constant. */ |
53 | static int emit_kdelta1(ASMState *as, Reg t, int32_t i) | 83 | static int emit_kdelta1(ASMState *as, Reg t, intptr_t i) |
54 | { | 84 | { |
55 | RegSet work = ~as->freeset & RSET_GPR; | 85 | RegSet work = ~as->freeset & RSET_GPR; |
56 | while (work) { | 86 | while (work) { |
@@ -58,9 +88,10 @@ static int emit_kdelta1(ASMState *as, Reg t, int32_t i) | |||
58 | IRRef ref = regcost_ref(as->cost[r]); | 88 | IRRef ref = regcost_ref(as->cost[r]); |
59 | lua_assert(r != t); | 89 | lua_assert(r != t); |
60 | if (ref < ASMREF_L) { | 90 | if (ref < ASMREF_L) { |
61 | int32_t delta = i - (ra_iskref(ref) ? ra_krefk(as, ref) : IR(ref)->i); | 91 | intptr_t delta = (intptr_t)((uintptr_t)i - |
92 | (uintptr_t)(ra_iskref(ref) ? ra_krefk(as, ref) : get_kval(IR(ref)))); | ||
62 | if (checki16(delta)) { | 93 | if (checki16(delta)) { |
63 | emit_tsi(as, MIPSI_ADDIU, t, r, delta); | 94 | emit_tsi(as, MIPSI_AADDIU, t, r, delta); |
64 | return 1; | 95 | return 1; |
65 | } | 96 | } |
66 | } | 97 | } |
@@ -76,8 +107,8 @@ static void emit_loadi(ASMState *as, Reg r, int32_t i) | |||
76 | emit_ti(as, MIPSI_LI, r, i); | 107 | emit_ti(as, MIPSI_LI, r, i); |
77 | } else { | 108 | } else { |
78 | if ((i & 0xffff)) { | 109 | if ((i & 0xffff)) { |
79 | int32_t jgl = i32ptr(J2G(as->J)); | 110 | intptr_t jgl = (intptr_t)(void *)J2G(as->J); |
80 | if ((uint32_t)(i-jgl) < 65536) { | 111 | if ((uintptr_t)(i-jgl) < 65536) { |
81 | emit_tsi(as, MIPSI_ADDIU, r, RID_JGL, i-jgl-32768); | 112 | emit_tsi(as, MIPSI_ADDIU, r, RID_JGL, i-jgl-32768); |
82 | return; | 113 | return; |
83 | } else if (emit_kdelta1(as, r, i)) { | 114 | } else if (emit_kdelta1(as, r, i)) { |
@@ -92,7 +123,39 @@ static void emit_loadi(ASMState *as, Reg r, int32_t i) | |||
92 | } | 123 | } |
93 | } | 124 | } |
94 | 125 | ||
126 | #if LJ_64 | ||
127 | /* Load a 64 bit constant into a GPR. */ | ||
128 | static void emit_loadu64(ASMState *as, Reg r, uint64_t u64) | ||
129 | { | ||
130 | if (checki32((int64_t)u64)) { | ||
131 | emit_loadi(as, r, (int32_t)u64); | ||
132 | } else { | ||
133 | uint64_t delta = u64 - (uint64_t)(void *)J2G(as->J); | ||
134 | if (delta < 65536) { | ||
135 | emit_tsi(as, MIPSI_DADDIU, r, RID_JGL, (int32_t)(delta-32768)); | ||
136 | } else if (emit_kdelta1(as, r, (intptr_t)u64)) { | ||
137 | return; | ||
138 | } else { | ||
139 | if ((u64 & 0xffff)) { | ||
140 | emit_tsi(as, MIPSI_ORI, r, r, u64 & 0xffff); | ||
141 | } | ||
142 | if (((u64 >> 16) & 0xffff)) { | ||
143 | emit_dta(as, MIPSI_DSLL, r, r, 16); | ||
144 | emit_tsi(as, MIPSI_ORI, r, r, (u64 >> 16) & 0xffff); | ||
145 | emit_dta(as, MIPSI_DSLL, r, r, 16); | ||
146 | } else { | ||
147 | emit_dta(as, MIPSI_DSLL32, r, r, 0); | ||
148 | } | ||
149 | emit_loadi(as, r, (int32_t)(u64 >> 32)); | ||
150 | } | ||
151 | /* TODO: There are probably more optimization opportunities. */ | ||
152 | } | ||
153 | } | ||
154 | |||
155 | #define emit_loada(as, r, addr) emit_loadu64(as, (r), u64ptr((addr))) | ||
156 | #else | ||
95 | #define emit_loada(as, r, addr) emit_loadi(as, (r), i32ptr((addr))) | 157 | #define emit_loada(as, r, addr) emit_loadi(as, (r), i32ptr((addr))) |
158 | #endif | ||
96 | 159 | ||
97 | static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow); | 160 | static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow); |
98 | static void ra_allockreg(ASMState *as, intptr_t k, Reg r); | 161 | static void ra_allockreg(ASMState *as, intptr_t k, Reg r); |
@@ -100,8 +163,8 @@ static void ra_allockreg(ASMState *as, intptr_t k, Reg r); | |||
100 | /* Get/set from constant pointer. */ | 163 | /* Get/set from constant pointer. */ |
101 | static void emit_lsptr(ASMState *as, MIPSIns mi, Reg r, void *p, RegSet allow) | 164 | static void emit_lsptr(ASMState *as, MIPSIns mi, Reg r, void *p, RegSet allow) |
102 | { | 165 | { |
103 | int32_t jgl = i32ptr(J2G(as->J)); | 166 | intptr_t jgl = (intptr_t)(J2G(as->J)); |
104 | int32_t i = i32ptr(p); | 167 | intptr_t i = (intptr_t)(p); |
105 | Reg base; | 168 | Reg base; |
106 | if ((uint32_t)(i-jgl) < 65536) { | 169 | if ((uint32_t)(i-jgl) < 65536) { |
107 | i = i-jgl-32768; | 170 | i = i-jgl-32768; |
@@ -112,8 +175,24 @@ static void emit_lsptr(ASMState *as, MIPSIns mi, Reg r, void *p, RegSet allow) | |||
112 | emit_tsi(as, mi, r, base, i); | 175 | emit_tsi(as, mi, r, base, i); |
113 | } | 176 | } |
114 | 177 | ||
178 | #if LJ_64 | ||
179 | static void emit_loadk64(ASMState *as, Reg r, IRIns *ir) | ||
180 | { | ||
181 | const uint64_t *k = &ir_k64(ir)->u64; | ||
182 | Reg r64 = r; | ||
183 | if (rset_test(RSET_FPR, r)) { | ||
184 | r64 = RID_TMP; | ||
185 | emit_tg(as, MIPSI_DMTC1, r64, r); | ||
186 | } | ||
187 | if ((uint32_t)((intptr_t)k-(intptr_t)J2G(as->J)) < 65536) | ||
188 | emit_lsptr(as, MIPSI_LD, r64, (void *)k, 0); | ||
189 | else | ||
190 | emit_loadu64(as, r64, *k); | ||
191 | } | ||
192 | #else | ||
115 | #define emit_loadk64(as, r, ir) \ | 193 | #define emit_loadk64(as, r, ir) \ |
116 | emit_lsptr(as, MIPSI_LDC1, ((r) & 31), (void *)&ir_knum((ir))->u64, RSET_GPR) | 194 | emit_lsptr(as, MIPSI_LDC1, ((r) & 31), (void *)&ir_knum((ir))->u64, RSET_GPR) |
195 | #endif | ||
117 | 196 | ||
118 | /* Get/set global_State fields. */ | 197 | /* Get/set global_State fields. */ |
119 | static void emit_lsglptr(ASMState *as, MIPSIns mi, Reg r, int32_t ofs) | 198 | static void emit_lsglptr(ASMState *as, MIPSIns mi, Reg r, int32_t ofs) |
@@ -122,9 +201,9 @@ static void emit_lsglptr(ASMState *as, MIPSIns mi, Reg r, int32_t ofs) | |||
122 | } | 201 | } |
123 | 202 | ||
124 | #define emit_getgl(as, r, field) \ | 203 | #define emit_getgl(as, r, field) \ |
125 | emit_lsglptr(as, MIPSI_LW, (r), (int32_t)offsetof(global_State, field)) | 204 | emit_lsglptr(as, MIPSI_AL, (r), (int32_t)offsetof(global_State, field)) |
126 | #define emit_setgl(as, r, field) \ | 205 | #define emit_setgl(as, r, field) \ |
127 | emit_lsglptr(as, MIPSI_SW, (r), (int32_t)offsetof(global_State, field)) | 206 | emit_lsglptr(as, MIPSI_AS, (r), (int32_t)offsetof(global_State, field)) |
128 | 207 | ||
129 | /* Trace number is determined from per-trace exit stubs. */ | 208 | /* Trace number is determined from per-trace exit stubs. */ |
130 | #define emit_setvmstate(as, i) UNUSED(i) | 209 | #define emit_setvmstate(as, i) UNUSED(i) |
@@ -164,7 +243,7 @@ static void emit_call(ASMState *as, void *target, int needcfa) | |||
164 | needcfa = 1; | 243 | needcfa = 1; |
165 | } | 244 | } |
166 | as->mcp = p; | 245 | as->mcp = p; |
167 | if (needcfa) ra_allockreg(as, i32ptr(target), RID_CFUNCADDR); | 246 | if (needcfa) ra_allockreg(as, (intptr_t)target, RID_CFUNCADDR); |
168 | } | 247 | } |
169 | 248 | ||
170 | /* -- Emit generic operations --------------------------------------------- */ | 249 | /* -- Emit generic operations --------------------------------------------- */ |
@@ -185,7 +264,7 @@ static void emit_movrr(ASMState *as, IRIns *ir, Reg dst, Reg src) | |||
185 | static void emit_loadofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs) | 264 | static void emit_loadofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs) |
186 | { | 265 | { |
187 | if (r < RID_MAX_GPR) | 266 | if (r < RID_MAX_GPR) |
188 | emit_tsi(as, MIPSI_LW, r, base, ofs); | 267 | emit_tsi(as, irt_is64(ir->t) ? MIPSI_LD : MIPSI_LW, r, base, ofs); |
189 | else | 268 | else |
190 | emit_tsi(as, irt_isnum(ir->t) ? MIPSI_LDC1 : MIPSI_LWC1, | 269 | emit_tsi(as, irt_isnum(ir->t) ? MIPSI_LDC1 : MIPSI_LWC1, |
191 | (r & 31), base, ofs); | 270 | (r & 31), base, ofs); |
@@ -195,7 +274,7 @@ static void emit_loadofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs) | |||
195 | static void emit_storeofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs) | 274 | static void emit_storeofs(ASMState *as, IRIns *ir, Reg r, Reg base, int32_t ofs) |
196 | { | 275 | { |
197 | if (r < RID_MAX_GPR) | 276 | if (r < RID_MAX_GPR) |
198 | emit_tsi(as, MIPSI_SW, r, base, ofs); | 277 | emit_tsi(as, irt_is64(ir->t) ? MIPSI_SD : MIPSI_SW, r, base, ofs); |
199 | else | 278 | else |
200 | emit_tsi(as, irt_isnum(ir->t) ? MIPSI_SDC1 : MIPSI_SWC1, | 279 | emit_tsi(as, irt_isnum(ir->t) ? MIPSI_SDC1 : MIPSI_SWC1, |
201 | (r&31), base, ofs); | 280 | (r&31), base, ofs); |
@@ -206,7 +285,7 @@ static void emit_addptr(ASMState *as, Reg r, int32_t ofs) | |||
206 | { | 285 | { |
207 | if (ofs) { | 286 | if (ofs) { |
208 | lua_assert(checki16(ofs)); | 287 | lua_assert(checki16(ofs)); |
209 | emit_tsi(as, MIPSI_ADDIU, r, r, ofs); | 288 | emit_tsi(as, MIPSI_AADDIU, r, r, ofs); |
210 | } | 289 | } |
211 | } | 290 | } |
212 | 291 | ||