diff options
| author | Mike Pall <mike> | 2017-02-20 03:43:10 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2017-02-20 03:43:10 +0100 |
| commit | a25c0b99b84558887887b8e298409dcf8605e5e3 (patch) | |
| tree | 8cb7b1db3cb0cd4f6cdd59540d39d986b502e471 /src | |
| parent | 4416e885d28c0f49d2c7bb3f9630ab23c22fbc9a (diff) | |
| download | luajit-a25c0b99b84558887887b8e298409dcf8605e5e3.tar.gz luajit-a25c0b99b84558887887b8e298409dcf8605e5e3.tar.bz2 luajit-a25c0b99b84558887887b8e298409dcf8605e5e3.zip | |
MIPS64, part 2: Add MIPS64 hard-float JIT compiler backend.
Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
Sponsored by Cisco Systems, Inc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/jit/dis_mips.lua | 45 | ||||
| -rw-r--r-- | src/jit/dis_mips64.lua | 17 | ||||
| -rw-r--r-- | src/jit/dis_mips64el.lua | 17 | ||||
| -rw-r--r-- | src/jit/dump.lua | 2 | ||||
| -rw-r--r-- | src/lj_arch.h | 4 | ||||
| -rw-r--r-- | src/lj_asm_mips.h | 673 | ||||
| -rw-r--r-- | src/lj_emit_mips.h | 107 | ||||
| -rw-r--r-- | src/lj_jit.h | 8 | ||||
| -rw-r--r-- | src/lj_mcode.c | 6 | ||||
| -rw-r--r-- | src/lj_snap.c | 3 | ||||
| -rw-r--r-- | src/lj_target_mips.h | 90 | ||||
| -rw-r--r-- | src/lj_trace.c | 11 | ||||
| -rw-r--r-- | src/vm_mips64.dasc | 237 |
13 files changed, 1022 insertions, 198 deletions
diff --git a/src/jit/dis_mips.lua b/src/jit/dis_mips.lua index fdd3d353..a12b8e62 100644 --- a/src/jit/dis_mips.lua +++ b/src/jit/dis_mips.lua | |||
| @@ -34,15 +34,17 @@ local map_special = { | |||
| 34 | "jrS", "jalrD1S", "movzDST", "movnDST", | 34 | "jrS", "jalrD1S", "movzDST", "movnDST", |
| 35 | "syscallY", "breakY", false, "sync", | 35 | "syscallY", "breakY", false, "sync", |
| 36 | "mfhiD", "mthiS", "mfloD", "mtloS", | 36 | "mfhiD", "mthiS", "mfloD", "mtloS", |
| 37 | false, false, false, false, | 37 | "dsllvDST", false, "dsrlvDST", "dsravDST", |
| 38 | "multST", "multuST", "divST", "divuST", | 38 | "multST", "multuST", "divST", "divuST", |
| 39 | false, false, false, false, | 39 | "dmultST", "dmultuST", "ddivST", "ddivuST", |
| 40 | "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", | 40 | "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", |
| 41 | "andDST", "or|moveDST0", "xorDST", "nor|notDST0", | 41 | "andDST", "or|moveDST0", "xorDST", "nor|notDST0", |
| 42 | false, false, "sltDST", "sltuDST", | 42 | false, false, "sltDST", "sltuDST", |
| 43 | false, false, false, false, | 43 | "daddDST", "dadduDST", "dsubDST", "dsubuDST", |
| 44 | "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", | 44 | "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", |
| 45 | "teqSTZ", false, "tneSTZ", | 45 | "teqSTZ", false, "tneSTZ", false, |
| 46 | "dsllDTA", false, "dsrlDTA", "dsraDTA", | ||
| 47 | "dsll32DTA", false, "dsrl32DTA", "dsra32DTA", | ||
| 46 | } | 48 | } |
| 47 | 49 | ||
| 48 | local map_special2 = { | 50 | local map_special2 = { |
| @@ -60,11 +62,17 @@ local map_bshfl = { | |||
| 60 | [24] = "sehDT", | 62 | [24] = "sehDT", |
| 61 | } | 63 | } |
| 62 | 64 | ||
| 65 | local map_dbshfl = { | ||
| 66 | shift = 6, mask = 31, | ||
| 67 | [2] = "dsbhDT", | ||
| 68 | [5] = "dshdDT", | ||
| 69 | } | ||
| 70 | |||
| 63 | local map_special3 = { | 71 | local map_special3 = { |
| 64 | shift = 0, mask = 63, | 72 | shift = 0, mask = 63, |
| 65 | [0] = "extTSAK", [4] = "insTSAL", | 73 | [0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK", |
| 66 | [32] = map_bshfl, | 74 | [4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL", |
| 67 | [59] = "rdhwrTD", | 75 | [32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD", |
| 68 | } | 76 | } |
| 69 | 77 | ||
| 70 | local map_regimm = { | 78 | local map_regimm = { |
| @@ -178,8 +186,8 @@ local map_cop1bc = { | |||
| 178 | 186 | ||
| 179 | local map_cop1 = { | 187 | local map_cop1 = { |
| 180 | shift = 21, mask = 31, | 188 | shift = 21, mask = 31, |
| 181 | [0] = "mfc1TG", false, "cfc1TG", "mfhc1TG", | 189 | [0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG", |
| 182 | "mtc1TG", false, "ctc1TG", "mthc1TG", | 190 | "mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG", |
| 183 | map_cop1bc, false, false, false, | 191 | map_cop1bc, false, false, false, |
| 184 | false, false, false, false, | 192 | false, false, false, false, |
| 185 | map_cop1s, map_cop1d, false, false, | 193 | map_cop1s, map_cop1d, false, false, |
| @@ -213,16 +221,16 @@ local map_pri = { | |||
| 213 | "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", | 221 | "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", |
| 214 | map_cop0, map_cop1, false, map_cop1x, | 222 | map_cop0, map_cop1, false, map_cop1x, |
| 215 | "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", | 223 | "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", |
| 216 | false, false, false, false, | 224 | "daddiTSI", "daddiuTSI", false, false, |
| 217 | map_special2, "jalxJ", false, map_special3, | 225 | map_special2, "jalxJ", false, map_special3, |
| 218 | "lbTSO", "lhTSO", "lwlTSO", "lwTSO", | 226 | "lbTSO", "lhTSO", "lwlTSO", "lwTSO", |
| 219 | "lbuTSO", "lhuTSO", "lwrTSO", false, | 227 | "lbuTSO", "lhuTSO", "lwrTSO", false, |
| 220 | "sbTSO", "shTSO", "swlTSO", "swTSO", | 228 | "sbTSO", "shTSO", "swlTSO", "swTSO", |
| 221 | false, false, "swrTSO", "cacheNSO", | 229 | false, false, "swrTSO", "cacheNSO", |
| 222 | "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", | 230 | "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", |
| 223 | false, "ldc1HSO", "ldc2TSO", false, | 231 | false, "ldc1HSO", "ldc2TSO", "ldTSO", |
| 224 | "scTSO", "swc1HSO", "swc2TSO", false, | 232 | "scTSO", "swc1HSO", "swc2TSO", false, |
| 225 | false, "sdc1HSO", "sdc2TSO", false, | 233 | false, "sdc1HSO", "sdc2TSO", "sdTSO", |
| 226 | } | 234 | } |
| 227 | 235 | ||
| 228 | ------------------------------------------------------------------------------ | 236 | ------------------------------------------------------------------------------ |
| @@ -306,6 +314,8 @@ local function disass_ins(ctx) | |||
| 306 | x = "f"..band(rshift(op, 21), 31) | 314 | x = "f"..band(rshift(op, 21), 31) |
| 307 | elseif p == "A" then | 315 | elseif p == "A" then |
| 308 | x = band(rshift(op, 6), 31) | 316 | x = band(rshift(op, 6), 31) |
| 317 | elseif p == "E" then | ||
| 318 | x = band(rshift(op, 6), 31) + 32 | ||
| 309 | elseif p == "M" then | 319 | elseif p == "M" then |
| 310 | x = band(rshift(op, 11), 31) | 320 | x = band(rshift(op, 11), 31) |
| 311 | elseif p == "N" then | 321 | elseif p == "N" then |
| @@ -315,8 +325,12 @@ local function disass_ins(ctx) | |||
| 315 | if x == 0 then x = nil end | 325 | if x == 0 then x = nil end |
| 316 | elseif p == "K" then | 326 | elseif p == "K" then |
| 317 | x = band(rshift(op, 11), 31) + 1 | 327 | x = band(rshift(op, 11), 31) + 1 |
| 328 | elseif p == "P" then | ||
| 329 | x = band(rshift(op, 11), 31) + 33 | ||
| 318 | elseif p == "L" then | 330 | elseif p == "L" then |
| 319 | x = band(rshift(op, 11), 31) - last + 1 | 331 | x = band(rshift(op, 11), 31) - last + 1 |
| 332 | elseif p == "Q" then | ||
| 333 | x = band(rshift(op, 11), 31) - last + 33 | ||
| 320 | elseif p == "I" then | 334 | elseif p == "I" then |
| 321 | x = arshift(lshift(op, 16), 16) | 335 | x = arshift(lshift(op, 16), 16) |
| 322 | elseif p == "U" then | 336 | elseif p == "U" then |
| @@ -330,11 +344,12 @@ local function disass_ins(ctx) | |||
| 330 | elseif p == "B" then | 344 | elseif p == "B" then |
| 331 | x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 16)*4 + 4 | 345 | x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 16)*4 + 4 |
| 332 | ctx.rel = x | 346 | ctx.rel = x |
| 333 | x = "0x"..tohex(x) | 347 | x = format("0x%08x", x) |
| 334 | elseif p == "J" then | 348 | elseif p == "J" then |
| 335 | x = band(ctx.addr + ctx.pos, 0xf0000000) + band(op, 0x03ffffff)*4 | 349 | local a = ctx.addr + ctx.pos |
| 350 | x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4 | ||
| 336 | ctx.rel = x | 351 | ctx.rel = x |
| 337 | x = "0x"..tohex(x) | 352 | x = format("0x%08x", x) |
| 338 | elseif p == "V" then | 353 | elseif p == "V" then |
| 339 | x = band(rshift(op, 8), 7) | 354 | x = band(rshift(op, 8), 7) |
| 340 | if x == 0 then x = nil end | 355 | if x == 0 then x = nil end |
diff --git a/src/jit/dis_mips64.lua b/src/jit/dis_mips64.lua new file mode 100644 index 00000000..c4374928 --- /dev/null +++ b/src/jit/dis_mips64.lua | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | ---------------------------------------------------------------------------- | ||
| 2 | -- LuaJIT MIPS64 disassembler wrapper module. | ||
| 3 | -- | ||
| 4 | -- Copyright (C) 2005-2017 Mike Pall. All rights reserved. | ||
| 5 | -- Released under the MIT license. See Copyright Notice in luajit.h | ||
| 6 | ---------------------------------------------------------------------------- | ||
| 7 | -- This module just exports the big-endian functions from the | ||
| 8 | -- MIPS disassembler module. All the interesting stuff is there. | ||
| 9 | ------------------------------------------------------------------------------ | ||
| 10 | |||
| 11 | local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") | ||
| 12 | return { | ||
| 13 | create = dis_mips.create, | ||
| 14 | disass = dis_mips.disass, | ||
| 15 | regname = dis_mips.regname | ||
| 16 | } | ||
| 17 | |||
diff --git a/src/jit/dis_mips64el.lua b/src/jit/dis_mips64el.lua new file mode 100644 index 00000000..2b1470af --- /dev/null +++ b/src/jit/dis_mips64el.lua | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | ---------------------------------------------------------------------------- | ||
| 2 | -- LuaJIT MIPS64EL disassembler wrapper module. | ||
| 3 | -- | ||
| 4 | -- Copyright (C) 2005-2017 Mike Pall. All rights reserved. | ||
| 5 | -- Released under the MIT license. See Copyright Notice in luajit.h | ||
| 6 | ---------------------------------------------------------------------------- | ||
| 7 | -- This module just exports the little-endian functions from the | ||
| 8 | -- MIPS disassembler module. All the interesting stuff is there. | ||
| 9 | ------------------------------------------------------------------------------ | ||
| 10 | |||
| 11 | local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips") | ||
| 12 | return { | ||
| 13 | create = dis_mips.create_el, | ||
| 14 | disass = dis_mips.disass_el, | ||
| 15 | regname = dis_mips.regname | ||
| 16 | } | ||
| 17 | |||
diff --git a/src/jit/dump.lua b/src/jit/dump.lua index 898ce9a1..2bea652b 100644 --- a/src/jit/dump.lua +++ b/src/jit/dump.lua | |||
| @@ -85,7 +85,7 @@ local nexitsym = 0 | |||
| 85 | local function fillsymtab_tr(tr, nexit) | 85 | local function fillsymtab_tr(tr, nexit) |
| 86 | local t = {} | 86 | local t = {} |
| 87 | symtabmt.__index = t | 87 | symtabmt.__index = t |
| 88 | if jit.arch == "mips" or jit.arch == "mipsel" then | 88 | if jit.arch:sub(1, 4) == "mips" then |
| 89 | t[traceexitstub(tr, 0)] = "exit" | 89 | t[traceexitstub(tr, 0)] = "exit" |
| 90 | return | 90 | return |
| 91 | end | 91 | end |
diff --git a/src/lj_arch.h b/src/lj_arch.h index 001111da..9bf6f481 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h | |||
| @@ -332,10 +332,12 @@ | |||
| 332 | #define LJ_ARCH_BITS 32 | 332 | #define LJ_ARCH_BITS 32 |
| 333 | #define LJ_TARGET_MIPS32 1 | 333 | #define LJ_TARGET_MIPS32 1 |
| 334 | #else | 334 | #else |
| 335 | #if LJ_ABI_SOFTFP || !LJ_ARCH_HASFPU | ||
| 336 | #define LJ_ARCH_NOJIT 1 /* NYI */ | ||
| 337 | #endif | ||
| 335 | #define LJ_ARCH_BITS 64 | 338 | #define LJ_ARCH_BITS 64 |
| 336 | #define LJ_TARGET_MIPS64 1 | 339 | #define LJ_TARGET_MIPS64 1 |
| 337 | #define LJ_TARGET_GC64 1 | 340 | #define LJ_TARGET_GC64 1 |
| 338 | #define LJ_ARCH_NOJIT 1 /* NYI */ | ||
| 339 | #endif | 341 | #endif |
| 340 | #define LJ_TARGET_MIPS 1 | 342 | #define LJ_TARGET_MIPS 1 |
| 341 | #define LJ_TARGET_EHRETREG 4 | 343 | #define LJ_TARGET_EHRETREG 4 |
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h index dd821c70..affe7d89 100644 --- a/src/lj_asm_mips.h +++ b/src/lj_asm_mips.h | |||
| @@ -23,7 +23,7 @@ static Reg ra_alloc1z(ASMState *as, IRRef ref, RegSet allow) | |||
| 23 | { | 23 | { |
| 24 | Reg r = IR(ref)->r; | 24 | Reg r = IR(ref)->r; |
| 25 | if (ra_noreg(r)) { | 25 | if (ra_noreg(r)) { |
| 26 | if (!(allow & RSET_FPR) && irref_isk(ref) && IR(ref)->i == 0) | 26 | if (!(allow & RSET_FPR) && irref_isk(ref) && get_kval(IR(ref)) == 0) |
| 27 | return RID_ZERO; | 27 | return RID_ZERO; |
| 28 | r = ra_allocref(as, ref, allow); | 28 | r = ra_allocref(as, ref, allow); |
| 29 | } else { | 29 | } else { |
| @@ -166,9 +166,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow) | |||
| 166 | } else if (ir->o == IR_UREFC) { | 166 | } else if (ir->o == IR_UREFC) { |
| 167 | if (irref_isk(ir->op1)) { | 167 | if (irref_isk(ir->op1)) { |
| 168 | GCfunc *fn = ir_kfunc(IR(ir->op1)); | 168 | GCfunc *fn = ir_kfunc(IR(ir->op1)); |
| 169 | int32_t ofs = i32ptr(&gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.tv); | 169 | intptr_t ofs = (intptr_t)&gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.tv; |
| 170 | int32_t jgl = (intptr_t)J2G(as->J); | 170 | intptr_t jgl = (intptr_t)J2G(as->J); |
| 171 | if ((uint32_t)(ofs-jgl) < 65536) { | 171 | if ((uintptr_t)(ofs-jgl) < 65536) { |
| 172 | *ofsp = ofs-jgl-32768; | 172 | *ofsp = ofs-jgl-32768; |
| 173 | return RID_JGL; | 173 | return RID_JGL; |
| 174 | } else { | 174 | } else { |
| @@ -190,20 +190,21 @@ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref, | |||
| 190 | Reg base; | 190 | Reg base; |
| 191 | if (ra_noreg(ir->r) && canfuse(as, ir)) { | 191 | if (ra_noreg(ir->r) && canfuse(as, ir)) { |
| 192 | if (ir->o == IR_ADD) { | 192 | if (ir->o == IR_ADD) { |
| 193 | int32_t ofs2; | 193 | intptr_t ofs2; |
| 194 | if (irref_isk(ir->op2) && (ofs2 = ofs + IR(ir->op2)->i, checki16(ofs2))) { | 194 | if (irref_isk(ir->op2) && (ofs2 = ofs + get_kval(IR(ir->op2)), |
| 195 | checki16(ofs2))) { | ||
| 195 | ref = ir->op1; | 196 | ref = ir->op1; |
| 196 | ofs = ofs2; | 197 | ofs = (int32_t)ofs2; |
| 197 | } | 198 | } |
| 198 | } else if (ir->o == IR_STRREF) { | 199 | } else if (ir->o == IR_STRREF) { |
| 199 | int32_t ofs2 = 65536; | 200 | intptr_t ofs2 = 65536; |
| 200 | lua_assert(ofs == 0); | 201 | lua_assert(ofs == 0); |
| 201 | ofs = (int32_t)sizeof(GCstr); | 202 | ofs = (int32_t)sizeof(GCstr); |
| 202 | if (irref_isk(ir->op2)) { | 203 | if (irref_isk(ir->op2)) { |
| 203 | ofs2 = ofs + IR(ir->op2)->i; | 204 | ofs2 = ofs + get_kval(IR(ir->op2)); |
| 204 | ref = ir->op1; | 205 | ref = ir->op1; |
| 205 | } else if (irref_isk(ir->op1)) { | 206 | } else if (irref_isk(ir->op1)) { |
| 206 | ofs2 = ofs + IR(ir->op1)->i; | 207 | ofs2 = ofs + get_kval(IR(ir->op1)); |
| 207 | ref = ir->op2; | 208 | ref = ir->op2; |
| 208 | } | 209 | } |
| 209 | if (!checki16(ofs2)) { | 210 | if (!checki16(ofs2)) { |
| @@ -211,7 +212,7 @@ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref, | |||
| 211 | Reg right, left = ra_alloc2(as, ir, allow); | 212 | Reg right, left = ra_alloc2(as, ir, allow); |
| 212 | right = (left >> 8); left &= 255; | 213 | right = (left >> 8); left &= 255; |
| 213 | emit_hsi(as, mi, rt, RID_TMP, ofs); | 214 | emit_hsi(as, mi, rt, RID_TMP, ofs); |
| 214 | emit_dst(as, MIPSI_ADDU, RID_TMP, left, right); | 215 | emit_dst(as, MIPSI_AADDU, RID_TMP, left, right); |
| 215 | return; | 216 | return; |
| 216 | } | 217 | } |
| 217 | ofs = ofs2; | 218 | ofs = ofs2; |
| @@ -227,7 +228,7 @@ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref, | |||
| 227 | static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | 228 | static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) |
| 228 | { | 229 | { |
| 229 | uint32_t n, nargs = CCI_XNARGS(ci); | 230 | uint32_t n, nargs = CCI_XNARGS(ci); |
| 230 | int32_t ofs = 16; | 231 | int32_t ofs = LJ_32 ? 16 : 0; |
| 231 | #if LJ_SOFTFP | 232 | #if LJ_SOFTFP |
| 232 | Reg gpr = REGARG_FIRSTGPR; | 233 | Reg gpr = REGARG_FIRSTGPR; |
| 233 | #else | 234 | #else |
| @@ -249,15 +250,15 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
| 249 | !(ci->flags & CCI_VARARG)) { | 250 | !(ci->flags & CCI_VARARG)) { |
| 250 | lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */ | 251 | lua_assert(rset_test(as->freeset, fpr)); /* Already evicted. */ |
| 251 | ra_leftov(as, fpr, ref); | 252 | ra_leftov(as, fpr, ref); |
| 252 | fpr += 2; | 253 | fpr += LJ_32 ? 2 : 1; |
| 253 | gpr += irt_isnum(ir->t) ? 2 : 1; | 254 | gpr += (LJ_32 && irt_isnum(ir->t)) ? 2 : 1; |
| 254 | } else | 255 | } else |
| 255 | #endif | 256 | #endif |
| 256 | { | 257 | { |
| 257 | #if !LJ_SOFTFP | 258 | #if LJ_32 && !LJ_SOFTFP |
| 258 | fpr = REGARG_LASTFPR+1; | 259 | fpr = REGARG_LASTFPR+1; |
| 259 | #endif | 260 | #endif |
| 260 | if (irt_isnum(ir->t)) gpr = (gpr+1) & ~1; | 261 | if (LJ_32 && irt_isnum(ir->t)) gpr = (gpr+1) & ~1; |
| 261 | if (gpr <= REGARG_LASTGPR) { | 262 | if (gpr <= REGARG_LASTGPR) { |
| 262 | lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */ | 263 | lua_assert(rset_test(as->freeset, gpr)); /* Already evicted. */ |
| 263 | #if !LJ_SOFTFP | 264 | #if !LJ_SOFTFP |
| @@ -269,35 +270,55 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
| 269 | r = ra_alloc1(as, ref, RSET_FPR); | 270 | r = ra_alloc1(as, ref, RSET_FPR); |
| 270 | as->freeset |= (of & RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1)); | 271 | as->freeset |= (of & RSET_RANGE(REGARG_FIRSTGPR, REGARG_LASTGPR+1)); |
| 271 | if (irt_isnum(ir->t)) { | 272 | if (irt_isnum(ir->t)) { |
| 273 | #if LJ_32 | ||
| 272 | emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?0:1), r+1); | 274 | emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?0:1), r+1); |
| 273 | emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?1:0), r); | 275 | emit_tg(as, MIPSI_MFC1, gpr+(LJ_BE?1:0), r); |
| 274 | lua_assert(rset_test(as->freeset, gpr+1)); /* Already evicted. */ | 276 | lua_assert(rset_test(as->freeset, gpr+1)); /* Already evicted. */ |
| 275 | gpr += 2; | 277 | gpr += 2; |
| 278 | #else | ||
| 279 | emit_tg(as, MIPSI_DMFC1, gpr, r); | ||
| 280 | gpr++; fpr++; | ||
| 281 | #endif | ||
| 276 | } else if (irt_isfloat(ir->t)) { | 282 | } else if (irt_isfloat(ir->t)) { |
| 277 | emit_tg(as, MIPSI_MFC1, gpr, r); | 283 | emit_tg(as, MIPSI_MFC1, gpr, r); |
| 278 | gpr++; | 284 | gpr++; |
| 285 | #if LJ_64 | ||
| 286 | fpr++; | ||
| 287 | #endif | ||
| 279 | } | 288 | } |
| 280 | } else | 289 | } else |
| 281 | #endif | 290 | #endif |
| 282 | { | 291 | { |
| 283 | ra_leftov(as, gpr, ref); | 292 | ra_leftov(as, gpr, ref); |
| 284 | gpr++; | 293 | gpr++; |
| 294 | #if LJ_64 | ||
| 295 | fpr++; | ||
| 296 | #endif | ||
| 285 | } | 297 | } |
| 286 | } else { | 298 | } else { |
| 287 | Reg r = ra_alloc1z(as, ref, !LJ_SOFTFP && irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); | 299 | Reg r = ra_alloc1z(as, ref, !LJ_SOFTFP && irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); |
| 300 | #if LJ_32 | ||
| 288 | if (irt_isnum(ir->t)) ofs = (ofs + 4) & ~4; | 301 | if (irt_isnum(ir->t)) ofs = (ofs + 4) & ~4; |
| 289 | emit_spstore(as, ir, r, ofs); | 302 | emit_spstore(as, ir, r, ofs); |
| 290 | ofs += irt_isnum(ir->t) ? 8 : 4; | 303 | ofs += irt_isnum(ir->t) ? 8 : 4; |
| 304 | #else | ||
| 305 | emit_spstore(as, ir, r, ofs + ((LJ_BE && (LJ_SOFTFP || r < RID_MAX_GPR) && !irt_is64(ir->t)) ? 4 : 0)); | ||
| 306 | ofs += 8; | ||
| 307 | #endif | ||
| 291 | } | 308 | } |
| 292 | } | 309 | } |
| 293 | } else { | 310 | } else { |
| 294 | #if !LJ_SOFTFP | 311 | #if !LJ_SOFTFP |
| 295 | fpr = REGARG_LASTFPR+1; | 312 | fpr = REGARG_LASTFPR+1; |
| 296 | #endif | 313 | #endif |
| 297 | if (gpr <= REGARG_LASTGPR) | 314 | if (gpr <= REGARG_LASTGPR) { |
| 298 | gpr++; | 315 | gpr++; |
| 299 | else | 316 | #if LJ_64 |
| 300 | ofs += 4; | 317 | fpr++; |
| 318 | #endif | ||
| 319 | } else { | ||
| 320 | ofs += LJ_32 ? 4 : 8; | ||
| 321 | } | ||
| 301 | } | 322 | } |
| 302 | checkmclim(as); | 323 | checkmclim(as); |
| 303 | } | 324 | } |
| @@ -307,15 +328,19 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
| 307 | static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | 328 | static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) |
| 308 | { | 329 | { |
| 309 | RegSet drop = RSET_SCRATCH; | 330 | RegSet drop = RSET_SCRATCH; |
| 331 | #if LJ_32 | ||
| 310 | int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); | 332 | int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); |
| 333 | #endif | ||
| 311 | #if !LJ_SOFTFP | 334 | #if !LJ_SOFTFP |
| 312 | if ((ci->flags & CCI_NOFPRCLOBBER)) | 335 | if ((ci->flags & CCI_NOFPRCLOBBER)) |
| 313 | drop &= ~RSET_FPR; | 336 | drop &= ~RSET_FPR; |
| 314 | #endif | 337 | #endif |
| 315 | if (ra_hasreg(ir->r)) | 338 | if (ra_hasreg(ir->r)) |
| 316 | rset_clear(drop, ir->r); /* Dest reg handled below. */ | 339 | rset_clear(drop, ir->r); /* Dest reg handled below. */ |
| 340 | #if LJ_32 | ||
| 317 | if (hiop && ra_hasreg((ir+1)->r)) | 341 | if (hiop && ra_hasreg((ir+1)->r)) |
| 318 | rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */ | 342 | rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */ |
| 343 | #endif | ||
| 319 | ra_evictset(as, drop); /* Evictions must be performed first. */ | 344 | ra_evictset(as, drop); /* Evictions must be performed first. */ |
| 320 | if (ra_used(ir)) { | 345 | if (ra_used(ir)) { |
| 321 | lua_assert(!irt_ispri(ir->t)); | 346 | lua_assert(!irt_ispri(ir->t)); |
| @@ -326,18 +351,28 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
| 326 | if (ra_hasreg(dest)) { | 351 | if (ra_hasreg(dest)) { |
| 327 | ra_free(as, dest); | 352 | ra_free(as, dest); |
| 328 | ra_modified(as, dest); | 353 | ra_modified(as, dest); |
| 354 | #if LJ_32 | ||
| 329 | emit_tg(as, MIPSI_MTC1, RID_RETHI, dest+1); | 355 | emit_tg(as, MIPSI_MTC1, RID_RETHI, dest+1); |
| 330 | emit_tg(as, MIPSI_MTC1, RID_RETLO, dest); | 356 | emit_tg(as, MIPSI_MTC1, RID_RETLO, dest); |
| 357 | #else | ||
| 358 | emit_tg(as, MIPSI_DMTC1, RID_RET, dest); | ||
| 359 | #endif | ||
| 331 | } | 360 | } |
| 332 | if (ofs) { | 361 | if (ofs) { |
| 362 | #if LJ_32 | ||
| 333 | emit_tsi(as, MIPSI_SW, RID_RETLO, RID_SP, ofs+(LJ_BE?4:0)); | 363 | emit_tsi(as, MIPSI_SW, RID_RETLO, RID_SP, ofs+(LJ_BE?4:0)); |
| 334 | emit_tsi(as, MIPSI_SW, RID_RETHI, RID_SP, ofs+(LJ_BE?0:4)); | 364 | emit_tsi(as, MIPSI_SW, RID_RETHI, RID_SP, ofs+(LJ_BE?0:4)); |
| 365 | #else | ||
| 366 | emit_tsi(as, MIPSI_SD, RID_RET, RID_SP, ofs); | ||
| 367 | #endif | ||
| 335 | } | 368 | } |
| 336 | } else { | 369 | } else { |
| 337 | ra_destreg(as, ir, RID_FPRET); | 370 | ra_destreg(as, ir, RID_FPRET); |
| 338 | } | 371 | } |
| 372 | #if LJ_32 | ||
| 339 | } else if (hiop) { | 373 | } else if (hiop) { |
| 340 | ra_destpair(as, ir); | 374 | ra_destpair(as, ir); |
| 375 | #endif | ||
| 341 | } else { | 376 | } else { |
| 342 | ra_destreg(as, ir, RID_RET); | 377 | ra_destreg(as, ir, RID_RET); |
| 343 | } | 378 | } |
| @@ -356,7 +391,7 @@ static void asm_callx(ASMState *as, IRIns *ir) | |||
| 356 | func = ir->op2; irf = IR(func); | 391 | func = ir->op2; irf = IR(func); |
| 357 | if (irf->o == IR_CARG) { func = irf->op1; irf = IR(func); } | 392 | if (irf->o == IR_CARG) { func = irf->op1; irf = IR(func); } |
| 358 | if (irref_isk(func)) { /* Call to constant address. */ | 393 | if (irref_isk(func)) { /* Call to constant address. */ |
| 359 | ci.func = (ASMFunction)(void *)(irf->i); | 394 | ci.func = (ASMFunction)(void *)get_kval(irf); |
| 360 | } else { /* Need specific register for indirect calls. */ | 395 | } else { /* Need specific register for indirect calls. */ |
| 361 | Reg r = ra_alloc1(as, func, RID2RSET(RID_CFUNCADDR)); | 396 | Reg r = ra_alloc1(as, func, RID2RSET(RID_CFUNCADDR)); |
| 362 | MCode *p = as->mcp; | 397 | MCode *p = as->mcp; |
| @@ -399,8 +434,8 @@ static void asm_retf(ASMState *as, IRIns *ir) | |||
| 399 | emit_setgl(as, base, jit_base); | 434 | emit_setgl(as, base, jit_base); |
| 400 | emit_addptr(as, base, -8*delta); | 435 | emit_addptr(as, base, -8*delta); |
| 401 | asm_guard(as, MIPSI_BNE, RID_TMP, | 436 | asm_guard(as, MIPSI_BNE, RID_TMP, |
| 402 | ra_allock(as, i32ptr(pc), rset_exclude(RSET_GPR, base))); | 437 | ra_allock(as, igcptr(pc), rset_exclude(RSET_GPR, base))); |
| 403 | emit_tsi(as, MIPSI_LW, RID_TMP, base, -8); | 438 | emit_tsi(as, MIPSI_AL, RID_TMP, base, -8); |
| 404 | } | 439 | } |
| 405 | 440 | ||
| 406 | /* -- Type conversions ---------------------------------------------------- */ | 441 | /* -- Type conversions ---------------------------------------------------- */ |
| @@ -435,10 +470,15 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
| 435 | #if !LJ_SOFTFP | 470 | #if !LJ_SOFTFP |
| 436 | int stfp = (st == IRT_NUM || st == IRT_FLOAT); | 471 | int stfp = (st == IRT_NUM || st == IRT_FLOAT); |
| 437 | #endif | 472 | #endif |
| 473 | #if LJ_64 | ||
| 474 | int st64 = (st == IRT_I64 || st == IRT_U64 || st == IRT_P64); | ||
| 475 | #endif | ||
| 438 | IRRef lref = ir->op1; | 476 | IRRef lref = ir->op1; |
| 477 | #if LJ_32 | ||
| 439 | lua_assert(!(irt_isint64(ir->t) || | 478 | lua_assert(!(irt_isint64(ir->t) || |
| 440 | (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ | 479 | (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ |
| 441 | #if LJ_SOFTFP | 480 | #endif |
| 481 | #if LJ_32 && LJ_SOFTFP | ||
| 442 | /* FP conversions are handled by SPLIT. */ | 482 | /* FP conversions are handled by SPLIT. */ |
| 443 | lua_assert(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT)); | 483 | lua_assert(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT)); |
| 444 | /* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */ | 484 | /* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */ |
| @@ -463,11 +503,40 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
| 463 | emit_tg(as, MIPSI_MTC1, RID_TMP, dest); | 503 | emit_tg(as, MIPSI_MTC1, RID_TMP, dest); |
| 464 | emit_dst(as, MIPSI_XOR, RID_TMP, RID_TMP, left); | 504 | emit_dst(as, MIPSI_XOR, RID_TMP, RID_TMP, left); |
| 465 | emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000); | 505 | emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000); |
| 506 | #if LJ_64 | ||
| 507 | } else if(st == IRT_U64) { /* U64 to FP conversion. */ | ||
| 508 | /* if (x >= 1u<<63) y = (double)(int64_t)(x&(1u<<63)-1) + pow(2.0, 63) */ | ||
| 509 | Reg left = ra_alloc1(as, lref, RSET_GPR); | ||
| 510 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, dest)); | ||
| 511 | MCLabel l_end = emit_label(as); | ||
| 512 | if (irt_isfloat(ir->t)) { | ||
| 513 | emit_fgh(as, MIPSI_ADD_S, dest, dest, tmp); | ||
| 514 | emit_lsptr(as, MIPSI_LWC1, (tmp & 31), (void *)&as->J->k32[LJ_K32_2P63], | ||
| 515 | rset_exclude(RSET_GPR, left)); | ||
| 516 | emit_fg(as, MIPSI_CVT_S_L, dest, dest); | ||
| 517 | } else { | ||
| 518 | emit_fgh(as, MIPSI_ADD_D, dest, dest, tmp); | ||
| 519 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), (void *)&as->J->k64[LJ_K64_2P63], | ||
| 520 | rset_exclude(RSET_GPR, left)); | ||
| 521 | emit_fg(as, MIPSI_CVT_D_L, dest, dest); | ||
| 522 | } | ||
| 523 | emit_branch(as, MIPSI_BGEZ, left, RID_ZERO, l_end); | ||
| 524 | emit_tg(as, MIPSI_DMTC1, RID_TMP, dest); | ||
| 525 | emit_tsml(as, MIPSI_DEXTM, RID_TMP, left, 30, 0); | ||
| 526 | #endif | ||
| 466 | } else { /* Integer to FP conversion. */ | 527 | } else { /* Integer to FP conversion. */ |
| 467 | Reg left = ra_alloc1(as, lref, RSET_GPR); | 528 | Reg left = ra_alloc1(as, lref, RSET_GPR); |
| 529 | #if LJ_32 | ||
| 468 | emit_fg(as, irt_isfloat(ir->t) ? MIPSI_CVT_S_W : MIPSI_CVT_D_W, | 530 | emit_fg(as, irt_isfloat(ir->t) ? MIPSI_CVT_S_W : MIPSI_CVT_D_W, |
| 469 | dest, dest); | 531 | dest, dest); |
| 470 | emit_tg(as, MIPSI_MTC1, left, dest); | 532 | emit_tg(as, MIPSI_MTC1, left, dest); |
| 533 | #else | ||
| 534 | MIPSIns mi = irt_isfloat(ir->t) ? | ||
| 535 | (st64 ? MIPSI_CVT_S_L : MIPSI_CVT_S_W) : | ||
| 536 | (st64 ? MIPSI_CVT_D_L : MIPSI_CVT_D_W); | ||
| 537 | emit_fg(as, mi, dest, dest); | ||
| 538 | emit_tg(as, st64 ? MIPSI_DMTC1 : MIPSI_MTC1, left, dest); | ||
| 539 | #endif | ||
| 471 | } | 540 | } |
| 472 | } else if (stfp) { /* FP to integer conversion. */ | 541 | } else if (stfp) { /* FP to integer conversion. */ |
| 473 | if (irt_isguard(ir->t)) { | 542 | if (irt_isguard(ir->t)) { |
| @@ -478,7 +547,7 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
| 478 | Reg dest = ra_dest(as, ir, RSET_GPR); | 547 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 479 | Reg left = ra_alloc1(as, lref, RSET_FPR); | 548 | Reg left = ra_alloc1(as, lref, RSET_FPR); |
| 480 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); | 549 | Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); |
| 481 | if (irt_isu32(ir->t)) { | 550 | if (irt_isu32(ir->t)) { /* FP to U32 conversion. */ |
| 482 | /* y = (int)floor(x - 2147483648.0) ^ 0x80000000 */ | 551 | /* y = (int)floor(x - 2147483648.0) ^ 0x80000000 */ |
| 483 | emit_dst(as, MIPSI_XOR, dest, dest, RID_TMP); | 552 | emit_dst(as, MIPSI_XOR, dest, dest, RID_TMP); |
| 484 | emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000); | 553 | emit_ti(as, MIPSI_LUI, RID_TMP, 0x8000); |
| @@ -493,10 +562,50 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
| 493 | else | 562 | else |
| 494 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), | 563 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), |
| 495 | (void *)&as->J->k64[LJ_K64_2P31], RSET_GPR); | 564 | (void *)&as->J->k64[LJ_K64_2P31], RSET_GPR); |
| 565 | #if LJ_64 | ||
| 566 | } else if (irt_isu64(ir->t)) { /* FP to U64 conversion. */ | ||
| 567 | MCLabel l_end; | ||
| 568 | emit_tg(as, MIPSI_DMFC1, dest, tmp); | ||
| 569 | l_end = emit_label(as); | ||
| 570 | /* For inputs >= 2^63 add -2^64 and convert again. */ | ||
| 571 | if (st == IRT_NUM) { | ||
| 572 | emit_fg(as, MIPSI_TRUNC_L_D, tmp, tmp); | ||
| 573 | emit_fgh(as, MIPSI_ADD_D, tmp, left, tmp); | ||
| 574 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), | ||
| 575 | (void *)&as->J->k64[LJ_K64_M2P64], | ||
| 576 | rset_exclude(RSET_GPR, dest)); | ||
| 577 | emit_fg(as, MIPSI_TRUNC_L_D, tmp, left); /* Delay slot. */ | ||
| 578 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); | ||
| 579 | emit_fgh(as, MIPSI_C_OLT_D, 0, left, tmp); | ||
| 580 | emit_lsptr(as, MIPSI_LDC1, (tmp & 31), | ||
| 581 | (void *)&as->J->k64[LJ_K64_2P63], | ||
| 582 | rset_exclude(RSET_GPR, dest)); | ||
| 583 | } else { | ||
| 584 | emit_fg(as, MIPSI_TRUNC_L_S, tmp, tmp); | ||
| 585 | emit_fgh(as, MIPSI_ADD_S, tmp, left, tmp); | ||
| 586 | emit_lsptr(as, MIPSI_LWC1, (tmp & 31), | ||
| 587 | (void *)&as->J->k32[LJ_K32_M2P64], | ||
| 588 | rset_exclude(RSET_GPR, dest)); | ||
| 589 | emit_fg(as, MIPSI_TRUNC_L_S, tmp, left); /* Delay slot. */ | ||
| 590 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); | ||
| 591 | emit_fgh(as, MIPSI_C_OLT_S, 0, left, tmp); | ||
| 592 | emit_lsptr(as, MIPSI_LWC1, (tmp & 31), | ||
| 593 | (void *)&as->J->k32[LJ_K32_2P63], | ||
| 594 | rset_exclude(RSET_GPR, dest)); | ||
| 595 | } | ||
| 596 | #endif | ||
| 496 | } else { | 597 | } else { |
| 598 | #if LJ_32 | ||
| 497 | emit_tg(as, MIPSI_MFC1, dest, tmp); | 599 | emit_tg(as, MIPSI_MFC1, dest, tmp); |
| 498 | emit_fg(as, st == IRT_FLOAT ? MIPSI_TRUNC_W_S : MIPSI_TRUNC_W_D, | 600 | emit_fg(as, st == IRT_FLOAT ? MIPSI_TRUNC_W_S : MIPSI_TRUNC_W_D, |
| 499 | tmp, left); | 601 | tmp, left); |
| 602 | #else | ||
| 603 | MIPSIns mi = irt_is64(ir->t) ? | ||
| 604 | (st == IRT_NUM ? MIPSI_TRUNC_L_D : MIPSI_TRUNC_L_S) : | ||
| 605 | (st == IRT_NUM ? MIPSI_TRUNC_W_D : MIPSI_TRUNC_W_S); | ||
| 606 | emit_tg(as, irt_is64(ir->t) ? MIPSI_DMFC1 : MIPSI_MFC1, dest, left); | ||
| 607 | emit_fg(as, mi, left, left); | ||
| 608 | #endif | ||
| 500 | } | 609 | } |
| 501 | } | 610 | } |
| 502 | } else | 611 | } else |
| @@ -507,7 +616,7 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
| 507 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); | 616 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); |
| 508 | lua_assert(irt_isint(ir->t) || irt_isu32(ir->t)); | 617 | lua_assert(irt_isint(ir->t) || irt_isu32(ir->t)); |
| 509 | if ((ir->op2 & IRCONV_SEXT)) { | 618 | if ((ir->op2 & IRCONV_SEXT)) { |
| 510 | if ((as->flags & JIT_F_MIPSXXR2)) { | 619 | if (LJ_64 || (as->flags & JIT_F_MIPSXXR2)) { |
| 511 | emit_dst(as, st == IRT_I8 ? MIPSI_SEB : MIPSI_SEH, dest, 0, left); | 620 | emit_dst(as, st == IRT_I8 ? MIPSI_SEB : MIPSI_SEH, dest, 0, left); |
| 512 | } else { | 621 | } else { |
| 513 | uint32_t shift = st == IRT_I8 ? 24 : 16; | 622 | uint32_t shift = st == IRT_I8 ? 24 : 16; |
| @@ -519,8 +628,35 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
| 519 | (int32_t)(st == IRT_U8 ? 0xff : 0xffff)); | 628 | (int32_t)(st == IRT_U8 ? 0xff : 0xffff)); |
| 520 | } | 629 | } |
| 521 | } else { /* 32/64 bit integer conversions. */ | 630 | } else { /* 32/64 bit integer conversions. */ |
| 631 | #if LJ_32 | ||
| 522 | /* Only need to handle 32/32 bit no-op (cast) on 32 bit archs. */ | 632 | /* Only need to handle 32/32 bit no-op (cast) on 32 bit archs. */ |
| 523 | ra_leftov(as, dest, lref); /* Do nothing, but may need to move regs. */ | 633 | ra_leftov(as, dest, lref); /* Do nothing, but may need to move regs. */ |
| 634 | #else | ||
| 635 | if (irt_is64(ir->t)) { | ||
| 636 | if (st64) { | ||
| 637 | /* 64/64 bit no-op (cast)*/ | ||
| 638 | ra_leftov(as, dest, lref); | ||
| 639 | } else { | ||
| 640 | Reg left = ra_alloc1(as, lref, RSET_GPR); | ||
| 641 | if ((ir->op2 & IRCONV_SEXT)) { /* 32 to 64 bit sign extension. */ | ||
| 642 | emit_dta(as, MIPSI_SLL, dest, left, 0); | ||
| 643 | } else { /* 32 to 64 bit zero extension. */ | ||
| 644 | emit_tsml(as, MIPSI_DEXT, dest, left, 31, 0); | ||
| 645 | } | ||
| 646 | } | ||
| 647 | } else { | ||
| 648 | if (st64) { | ||
| 649 | /* This is either a 32 bit reg/reg mov which zeroes the hiword | ||
| 650 | ** or a load of the loword from a 64 bit address. | ||
| 651 | */ | ||
| 652 | Reg left = ra_alloc1(as, lref, RSET_GPR); | ||
| 653 | emit_tsml(as, MIPSI_DEXT, dest, left, 31, 0); | ||
| 654 | } else { /* 32/32 bit no-op (cast). */ | ||
| 655 | /* Do nothing, but may need to move regs. */ | ||
| 656 | ra_leftov(as, dest, lref); | ||
| 657 | } | ||
| 658 | } | ||
| 659 | #endif | ||
| 524 | } | 660 | } |
| 525 | } | 661 | } |
| 526 | } | 662 | } |
| @@ -563,23 +699,50 @@ static void asm_strto(ASMState *as, IRIns *ir) | |||
| 563 | args[1] = ASMREF_TMP1; /* TValue *n */ | 699 | args[1] = ASMREF_TMP1; /* TValue *n */ |
| 564 | asm_gencall(as, ci, args); | 700 | asm_gencall(as, ci, args); |
| 565 | /* Store the result to the spill slot or temp slots. */ | 701 | /* Store the result to the spill slot or temp slots. */ |
| 566 | emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), | 702 | emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), |
| 567 | RID_SP, ofs); | 703 | RID_SP, ofs); |
| 568 | } | 704 | } |
| 569 | 705 | ||
| 570 | /* -- Memory references --------------------------------------------------- */ | 706 | /* -- Memory references --------------------------------------------------- */ |
| 571 | 707 | ||
| 708 | #if LJ_64 | ||
| 709 | /* Store tagged value for ref at base+ofs. */ | ||
| 710 | static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref) | ||
| 711 | { | ||
| 712 | RegSet allow = rset_exclude(RSET_GPR, base); | ||
| 713 | IRIns *ir = IR(ref); | ||
| 714 | lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t)); | ||
| 715 | if (irref_isk(ref)) { | ||
| 716 | TValue k; | ||
| 717 | lj_ir_kvalue(as->J->L, &k, ir); | ||
| 718 | emit_tsi(as, MIPSI_SD, ra_allock(as, (int64_t)k.u64, allow), base, ofs); | ||
| 719 | } else { | ||
| 720 | Reg src = ra_alloc1(as, ref, allow); | ||
| 721 | Reg type = ra_allock(as, (int64_t)irt_toitype(ir->t) << 47, | ||
| 722 | rset_exclude(allow, src)); | ||
| 723 | emit_tsi(as, MIPSI_SD, RID_TMP, base, ofs); | ||
| 724 | if (irt_isinteger(ir->t)) { | ||
| 725 | emit_dst(as, MIPSI_DADDU, RID_TMP, RID_TMP, type); | ||
| 726 | emit_tsml(as, MIPSI_DEXT, RID_TMP, src, 31, 0); | ||
| 727 | } else { | ||
| 728 | emit_dst(as, MIPSI_DADDU, RID_TMP, src, type); | ||
| 729 | } | ||
| 730 | } | ||
| 731 | } | ||
| 732 | #endif | ||
| 733 | |||
| 572 | /* Get pointer to TValue. */ | 734 | /* Get pointer to TValue. */ |
| 573 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | 735 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) |
| 574 | { | 736 | { |
| 575 | IRIns *ir = IR(ref); | 737 | IRIns *ir = IR(ref); |
| 576 | if (irt_isnum(ir->t)) { | 738 | if (irt_isnum(ir->t)) { |
| 577 | if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ | 739 | if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ |
| 578 | ra_allockreg(as, i32ptr(ir_knum(ir)), dest); | 740 | ra_allockreg(as, igcptr(ir_knum(ir)), dest); |
| 579 | else /* Otherwise force a spill and use the spill slot. */ | 741 | else /* Otherwise force a spill and use the spill slot. */ |
| 580 | emit_tsi(as, MIPSI_ADDIU, dest, RID_SP, ra_spill(as, ir)); | 742 | emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir)); |
| 581 | } else { | 743 | } else { |
| 582 | /* Otherwise use g->tmptv to hold the TValue. */ | 744 | /* Otherwise use g->tmptv to hold the TValue. */ |
| 745 | #if LJ_32 | ||
| 583 | RegSet allow = rset_exclude(RSET_GPR, dest); | 746 | RegSet allow = rset_exclude(RSET_GPR, dest); |
| 584 | Reg type; | 747 | Reg type; |
| 585 | emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768)); | 748 | emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768)); |
| @@ -592,6 +755,11 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | |||
| 592 | else | 755 | else |
| 593 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 756 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); |
| 594 | emit_setgl(as, type, tmptv.it); | 757 | emit_setgl(as, type, tmptv.it); |
| 758 | #else | ||
| 759 | asm_tvstore64(as, dest, 0, ref); | ||
| 760 | emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, | ||
| 761 | (int32_t)(offsetof(global_State, tmptv)-32768)); | ||
| 762 | #endif | ||
| 595 | } | 763 | } |
| 596 | } | 764 | } |
| 597 | 765 | ||
| @@ -606,13 +774,13 @@ static void asm_aref(ASMState *as, IRIns *ir) | |||
| 606 | ofs += 8*IR(ir->op2)->i; | 774 | ofs += 8*IR(ir->op2)->i; |
| 607 | if (checki16(ofs)) { | 775 | if (checki16(ofs)) { |
| 608 | base = ra_alloc1(as, refa, RSET_GPR); | 776 | base = ra_alloc1(as, refa, RSET_GPR); |
| 609 | emit_tsi(as, MIPSI_ADDIU, dest, base, ofs); | 777 | emit_tsi(as, MIPSI_AADDIU, dest, base, ofs); |
| 610 | return; | 778 | return; |
| 611 | } | 779 | } |
| 612 | } | 780 | } |
| 613 | base = ra_alloc1(as, ir->op1, RSET_GPR); | 781 | base = ra_alloc1(as, ir->op1, RSET_GPR); |
| 614 | idx = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, base)); | 782 | idx = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, base)); |
| 615 | emit_dst(as, MIPSI_ADDU, dest, RID_TMP, base); | 783 | emit_dst(as, MIPSI_AADDU, dest, RID_TMP, base); |
| 616 | emit_dta(as, MIPSI_SLL, RID_TMP, idx, 3); | 784 | emit_dta(as, MIPSI_SLL, RID_TMP, idx, 3); |
| 617 | } | 785 | } |
| 618 | 786 | ||
| @@ -633,13 +801,14 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
| 633 | Reg key = RID_NONE, type = RID_NONE, tmpnum = RID_NONE, tmp1 = RID_TMP, tmp2; | 801 | Reg key = RID_NONE, type = RID_NONE, tmpnum = RID_NONE, tmp1 = RID_TMP, tmp2; |
| 634 | IRRef refkey = ir->op2; | 802 | IRRef refkey = ir->op2; |
| 635 | IRIns *irkey = IR(refkey); | 803 | IRIns *irkey = IR(refkey); |
| 804 | int isk = irref_isk(refkey); | ||
| 636 | IRType1 kt = irkey->t; | 805 | IRType1 kt = irkey->t; |
| 637 | uint32_t khash; | 806 | uint32_t khash; |
| 638 | MCLabel l_end, l_loop, l_next; | 807 | MCLabel l_end, l_loop, l_next; |
| 639 | 808 | ||
| 640 | rset_clear(allow, tab); | 809 | rset_clear(allow, tab); |
| 641 | #if LJ_SOFTFP | 810 | #if LJ_32 && LJ_SOFTFP |
| 642 | if (!irref_isk(refkey)) { | 811 | if (!isk) { |
| 643 | key = ra_alloc1(as, refkey, allow); | 812 | key = ra_alloc1(as, refkey, allow); |
| 644 | rset_clear(allow, key); | 813 | rset_clear(allow, key); |
| 645 | if (irkey[1].o == IR_HIOP) { | 814 | if (irkey[1].o == IR_HIOP) { |
| @@ -664,8 +833,10 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
| 664 | } else if (!irt_ispri(kt)) { | 833 | } else if (!irt_ispri(kt)) { |
| 665 | key = ra_alloc1(as, refkey, allow); | 834 | key = ra_alloc1(as, refkey, allow); |
| 666 | rset_clear(allow, key); | 835 | rset_clear(allow, key); |
| 836 | #if LJ_32 | ||
| 667 | type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); | 837 | type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); |
| 668 | rset_clear(allow, type); | 838 | rset_clear(allow, type); |
| 839 | #endif | ||
| 669 | } | 840 | } |
| 670 | #endif | 841 | #endif |
| 671 | tmp2 = ra_scratch(as, allow); | 842 | tmp2 = ra_scratch(as, allow); |
| @@ -679,9 +850,9 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
| 679 | else if (destused) | 850 | else if (destused) |
| 680 | emit_loada(as, dest, niltvg(J2G(as->J))); | 851 | emit_loada(as, dest, niltvg(J2G(as->J))); |
| 681 | /* Follow hash chain until the end. */ | 852 | /* Follow hash chain until the end. */ |
| 682 | emit_move(as, dest, tmp2); | 853 | emit_move(as, dest, tmp1); |
| 683 | l_loop = --as->mcp; | 854 | l_loop = --as->mcp; |
| 684 | emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, next)); | 855 | emit_tsi(as, MIPSI_AL, tmp1, dest, (int32_t)offsetof(Node, next)); |
| 685 | l_next = emit_label(as); | 856 | l_next = emit_label(as); |
| 686 | 857 | ||
| 687 | /* Type and value comparison. */ | 858 | /* Type and value comparison. */ |
| @@ -693,38 +864,66 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
| 693 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); | 864 | emit_branch(as, MIPSI_BC1T, 0, 0, l_end); |
| 694 | emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); | 865 | emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); |
| 695 | *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */ | 866 | *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */ |
| 696 | emit_branch(as, MIPSI_BEQ, tmp2, RID_ZERO, l_next); | 867 | emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next); |
| 697 | emit_tsi(as, MIPSI_SLTIU, tmp2, tmp2, (int32_t)LJ_TISNUM); | 868 | emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM); |
| 869 | #if LJ_32 | ||
| 698 | emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n)); | 870 | emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n)); |
| 699 | } else { | 871 | } else { |
| 700 | if (irt_ispri(kt)) { | 872 | if (irt_ispri(kt)) { |
| 701 | emit_branch(as, MIPSI_BEQ, tmp2, type, l_end); | 873 | emit_branch(as, MIPSI_BEQ, tmp1, type, l_end); |
| 702 | } else { | 874 | } else { |
| 703 | emit_branch(as, MIPSI_BEQ, tmp1, key, l_end); | 875 | emit_branch(as, MIPSI_BEQ, tmp2, key, l_end); |
| 704 | emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.gcr)); | 876 | emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, key.gcr)); |
| 705 | emit_branch(as, MIPSI_BNE, tmp2, type, l_next); | 877 | emit_branch(as, MIPSI_BNE, tmp1, type, l_next); |
| 878 | } | ||
| 879 | } | ||
| 880 | emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.it)); | ||
| 881 | *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu); | ||
| 882 | #else | ||
| 883 | emit_dta(as, MIPSI_DSRA32, tmp1, tmp1, 15); | ||
| 884 | emit_tg(as, MIPSI_DMTC1, tmp1, tmpnum); | ||
| 885 | emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64)); | ||
| 886 | } else if (irt_isaddr(kt)) { | ||
| 887 | Reg refk = tmp2; | ||
| 888 | if (isk) { | ||
| 889 | int64_t k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; | ||
| 890 | refk = ra_allock(as, k, allow); | ||
| 891 | rset_clear(allow, refk); | ||
| 706 | } | 892 | } |
| 893 | emit_branch(as, MIPSI_BEQ, tmp1, refk, l_end); | ||
| 894 | emit_tsi(as, MIPSI_LD, tmp1, dest, offsetof(Node, key)); | ||
| 895 | } else { | ||
| 896 | Reg pri = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); | ||
| 897 | rset_clear(allow, pri); | ||
| 898 | lua_assert(irt_ispri(kt) && !irt_isnil(kt)); | ||
| 899 | emit_branch(as, MIPSI_BEQ, tmp1, pri, l_end); | ||
| 900 | emit_tsi(as, MIPSI_LD, tmp1, dest, offsetof(Node, key)); | ||
| 901 | } | ||
| 902 | *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu); | ||
| 903 | if (!isk && irt_isaddr(kt)) { | ||
| 904 | type = ra_allock(as, (int64_t)irt_toitype(kt) << 47, allow); | ||
| 905 | emit_dst(as, MIPSI_DADDU, tmp2, key, type); | ||
| 906 | rset_clear(allow, type); | ||
| 707 | } | 907 | } |
| 708 | emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, key.it)); | 908 | #endif |
| 709 | *l_loop = MIPSI_BNE | MIPSF_S(tmp2) | ((as->mcp-l_loop-1) & 0xffffu); | ||
| 710 | 909 | ||
| 711 | /* Load main position relative to tab->node into dest. */ | 910 | /* Load main position relative to tab->node into dest. */ |
| 712 | khash = irref_isk(refkey) ? ir_khash(irkey) : 1; | 911 | khash = isk ? ir_khash(irkey) : 1; |
| 713 | if (khash == 0) { | 912 | if (khash == 0) { |
| 714 | emit_tsi(as, MIPSI_LW, dest, tab, (int32_t)offsetof(GCtab, node)); | 913 | emit_tsi(as, MIPSI_AL, dest, tab, (int32_t)offsetof(GCtab, node)); |
| 715 | } else { | 914 | } else { |
| 716 | Reg tmphash = tmp1; | 915 | Reg tmphash = tmp1; |
| 717 | if (irref_isk(refkey)) | 916 | if (isk) |
| 718 | tmphash = ra_allock(as, khash, allow); | 917 | tmphash = ra_allock(as, khash, allow); |
| 719 | emit_dst(as, MIPSI_ADDU, dest, dest, tmp1); | 918 | emit_dst(as, MIPSI_AADDU, dest, dest, tmp1); |
| 720 | lua_assert(sizeof(Node) == 24); | 919 | lua_assert(sizeof(Node) == 24); |
| 721 | emit_dst(as, MIPSI_SUBU, tmp1, tmp2, tmp1); | 920 | emit_dst(as, MIPSI_SUBU, tmp1, tmp2, tmp1); |
| 722 | emit_dta(as, MIPSI_SLL, tmp1, tmp1, 3); | 921 | emit_dta(as, MIPSI_SLL, tmp1, tmp1, 3); |
| 723 | emit_dta(as, MIPSI_SLL, tmp2, tmp1, 5); | 922 | emit_dta(as, MIPSI_SLL, tmp2, tmp1, 5); |
| 724 | emit_dst(as, MIPSI_AND, tmp1, tmp2, tmphash); | 923 | emit_dst(as, MIPSI_AND, tmp1, tmp2, tmphash); |
| 725 | emit_tsi(as, MIPSI_LW, dest, tab, (int32_t)offsetof(GCtab, node)); | 924 | emit_tsi(as, MIPSI_AL, dest, tab, (int32_t)offsetof(GCtab, node)); |
| 726 | emit_tsi(as, MIPSI_LW, tmp2, tab, (int32_t)offsetof(GCtab, hmask)); | 925 | emit_tsi(as, MIPSI_LW, tmp2, tab, (int32_t)offsetof(GCtab, hmask)); |
| 727 | if (irref_isk(refkey)) { | 926 | if (isk) { |
| 728 | /* Nothing to do. */ | 927 | /* Nothing to do. */ |
| 729 | } else if (irt_isstr(kt)) { | 928 | } else if (irt_isstr(kt)) { |
| 730 | emit_tsi(as, MIPSI_LW, tmp1, key, (int32_t)offsetof(GCstr, hash)); | 929 | emit_tsi(as, MIPSI_LW, tmp1, key, (int32_t)offsetof(GCstr, hash)); |
| @@ -734,6 +933,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
| 734 | emit_dst(as, MIPSI_XOR, tmp1, tmp1, tmp2); | 933 | emit_dst(as, MIPSI_XOR, tmp1, tmp1, tmp2); |
| 735 | emit_rotr(as, tmp1, tmp1, dest, (-HASH_ROT2-HASH_ROT1)&31); | 934 | emit_rotr(as, tmp1, tmp1, dest, (-HASH_ROT2-HASH_ROT1)&31); |
| 736 | emit_dst(as, MIPSI_SUBU, tmp2, tmp2, dest); | 935 | emit_dst(as, MIPSI_SUBU, tmp2, tmp2, dest); |
| 936 | #if LJ_32 | ||
| 737 | if (LJ_SOFTFP ? (irkey[1].o == IR_HIOP) : irt_isnum(kt)) { | 937 | if (LJ_SOFTFP ? (irkey[1].o == IR_HIOP) : irt_isnum(kt)) { |
| 738 | emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1); | 938 | emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1); |
| 739 | if ((as->flags & JIT_F_MIPSXXR2)) { | 939 | if ((as->flags & JIT_F_MIPSXXR2)) { |
| @@ -756,6 +956,23 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge) | |||
| 756 | emit_rotr(as, dest, tmp1, tmp2, (-HASH_ROT1)&31); | 956 | emit_rotr(as, dest, tmp1, tmp2, (-HASH_ROT1)&31); |
| 757 | emit_dst(as, MIPSI_ADDU, tmp1, key, ra_allock(as, HASH_BIAS, allow)); | 957 | emit_dst(as, MIPSI_ADDU, tmp1, key, ra_allock(as, HASH_BIAS, allow)); |
| 758 | } | 958 | } |
| 959 | #else | ||
| 960 | emit_dst(as, MIPSI_XOR, tmp2, tmp2, tmp1); | ||
| 961 | emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31); | ||
| 962 | if (irt_isnum(kt)) { | ||
| 963 | emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1); | ||
| 964 | emit_dta(as, MIPSI_DSRA32, tmp1, tmp1, 0); | ||
| 965 | emit_dta(as, MIPSI_SLL, tmp2, LJ_SOFTFP ? key : tmp1, 0); | ||
| 966 | #if !LJ_SOFTFP | ||
| 967 | emit_tg(as, MIPSI_DMFC1, tmp1, key); | ||
| 968 | #endif | ||
| 969 | } else { | ||
| 970 | checkmclim(as); | ||
| 971 | emit_dta(as, MIPSI_DSRA32, tmp1, tmp1, 0); | ||
| 972 | emit_dta(as, MIPSI_SLL, tmp2, key, 0); | ||
| 973 | emit_dst(as, MIPSI_DADDU, tmp1, key, type); | ||
| 974 | } | ||
| 975 | #endif | ||
| 759 | } | 976 | } |
| 760 | } | 977 | } |
| 761 | } | 978 | } |
| @@ -768,17 +985,24 @@ static void asm_hrefk(ASMState *as, IRIns *ir) | |||
| 768 | int32_t kofs = ofs + (int32_t)offsetof(Node, key); | 985 | int32_t kofs = ofs + (int32_t)offsetof(Node, key); |
| 769 | Reg dest = (ra_used(ir)||ofs > 32736) ? ra_dest(as, ir, RSET_GPR) : RID_NONE; | 986 | Reg dest = (ra_used(ir)||ofs > 32736) ? ra_dest(as, ir, RSET_GPR) : RID_NONE; |
| 770 | Reg node = ra_alloc1(as, ir->op1, RSET_GPR); | 987 | Reg node = ra_alloc1(as, ir->op1, RSET_GPR); |
| 771 | Reg key = RID_NONE, type = RID_TMP, idx = node; | ||
| 772 | RegSet allow = rset_exclude(RSET_GPR, node); | 988 | RegSet allow = rset_exclude(RSET_GPR, node); |
| 989 | Reg idx = node; | ||
| 990 | #if LJ_32 | ||
| 991 | Reg key = RID_NONE, type = RID_TMP; | ||
| 773 | int32_t lo, hi; | 992 | int32_t lo, hi; |
| 993 | #else | ||
| 994 | Reg key = ra_scratch(as, allow); | ||
| 995 | int64_t k; | ||
| 996 | #endif | ||
| 774 | lua_assert(ofs % sizeof(Node) == 0); | 997 | lua_assert(ofs % sizeof(Node) == 0); |
| 775 | if (ofs > 32736) { | 998 | if (ofs > 32736) { |
| 776 | idx = dest; | 999 | idx = dest; |
| 777 | rset_clear(allow, dest); | 1000 | rset_clear(allow, dest); |
| 778 | kofs = (int32_t)offsetof(Node, key); | 1001 | kofs = (int32_t)offsetof(Node, key); |
| 779 | } else if (ra_hasreg(dest)) { | 1002 | } else if (ra_hasreg(dest)) { |
| 780 | emit_tsi(as, MIPSI_ADDIU, dest, node, ofs); | 1003 | emit_tsi(as, MIPSI_AADDIU, dest, node, ofs); |
| 781 | } | 1004 | } |
| 1005 | #if LJ_32 | ||
| 782 | if (!irt_ispri(irkey->t)) { | 1006 | if (!irt_ispri(irkey->t)) { |
| 783 | key = ra_scratch(as, allow); | 1007 | key = ra_scratch(as, allow); |
| 784 | rset_clear(allow, key); | 1008 | rset_clear(allow, key); |
| @@ -797,8 +1021,20 @@ nolo: | |||
| 797 | asm_guard(as, MIPSI_BNE, type, hi ? ra_allock(as, hi, allow) : RID_ZERO); | 1021 | asm_guard(as, MIPSI_BNE, type, hi ? ra_allock(as, hi, allow) : RID_ZERO); |
| 798 | if (ra_hasreg(key)) emit_tsi(as, MIPSI_LW, key, idx, kofs+(LJ_BE?4:0)); | 1022 | if (ra_hasreg(key)) emit_tsi(as, MIPSI_LW, key, idx, kofs+(LJ_BE?4:0)); |
| 799 | emit_tsi(as, MIPSI_LW, type, idx, kofs+(LJ_BE?0:4)); | 1023 | emit_tsi(as, MIPSI_LW, type, idx, kofs+(LJ_BE?0:4)); |
| 1024 | #else | ||
| 1025 | if (irt_ispri(irkey->t)) { | ||
| 1026 | lua_assert(!irt_isnil(irkey->t)); | ||
| 1027 | k = ~((int64_t)~irt_toitype(irkey->t) << 47); | ||
| 1028 | } else if (irt_isnum(irkey->t)) { | ||
| 1029 | k = (int64_t)ir_knum(irkey)->u64; | ||
| 1030 | } else { | ||
| 1031 | k = ((int64_t)irt_toitype(irkey->t) << 47) | (int64_t)ir_kgc(irkey); | ||
| 1032 | } | ||
| 1033 | asm_guard(as, MIPSI_BNE, key, ra_allock(as, k, allow)); | ||
| 1034 | emit_tsi(as, MIPSI_LD, key, idx, kofs); | ||
| 1035 | #endif | ||
| 800 | if (ofs > 32736) | 1036 | if (ofs > 32736) |
| 801 | emit_tsi(as, MIPSI_ADDU, dest, node, ra_allock(as, ofs, allow)); | 1037 | emit_tsi(as, MIPSI_AADDU, dest, node, ra_allock(as, ofs, allow)); |
| 802 | } | 1038 | } |
| 803 | 1039 | ||
| 804 | static void asm_uref(ASMState *as, IRIns *ir) | 1040 | static void asm_uref(ASMState *as, IRIns *ir) |
| @@ -807,19 +1043,19 @@ static void asm_uref(ASMState *as, IRIns *ir) | |||
| 807 | if (irref_isk(ir->op1)) { | 1043 | if (irref_isk(ir->op1)) { |
| 808 | GCfunc *fn = ir_kfunc(IR(ir->op1)); | 1044 | GCfunc *fn = ir_kfunc(IR(ir->op1)); |
| 809 | MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v; | 1045 | MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v; |
| 810 | emit_lsptr(as, MIPSI_LW, dest, v, RSET_GPR); | 1046 | emit_lsptr(as, MIPSI_AL, dest, v, RSET_GPR); |
| 811 | } else { | 1047 | } else { |
| 812 | Reg uv = ra_scratch(as, RSET_GPR); | 1048 | Reg uv = ra_scratch(as, RSET_GPR); |
| 813 | Reg func = ra_alloc1(as, ir->op1, RSET_GPR); | 1049 | Reg func = ra_alloc1(as, ir->op1, RSET_GPR); |
| 814 | if (ir->o == IR_UREFC) { | 1050 | if (ir->o == IR_UREFC) { |
| 815 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); | 1051 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); |
| 816 | emit_tsi(as, MIPSI_ADDIU, dest, uv, (int32_t)offsetof(GCupval, tv)); | 1052 | emit_tsi(as, MIPSI_AADDIU, dest, uv, (int32_t)offsetof(GCupval, tv)); |
| 817 | emit_tsi(as, MIPSI_LBU, RID_TMP, uv, (int32_t)offsetof(GCupval, closed)); | 1053 | emit_tsi(as, MIPSI_LBU, RID_TMP, uv, (int32_t)offsetof(GCupval, closed)); |
| 818 | } else { | 1054 | } else { |
| 819 | emit_tsi(as, MIPSI_LW, dest, uv, (int32_t)offsetof(GCupval, v)); | 1055 | emit_tsi(as, MIPSI_AL, dest, uv, (int32_t)offsetof(GCupval, v)); |
| 820 | } | 1056 | } |
| 821 | emit_tsi(as, MIPSI_LW, uv, func, | 1057 | emit_tsi(as, MIPSI_AL, uv, func, (int32_t)offsetof(GCfuncL, uvptr) + |
| 822 | (int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8)); | 1058 | (int32_t)sizeof(MRef) * (int32_t)(ir->op2 >> 8)); |
| 823 | } | 1059 | } |
| 824 | } | 1060 | } |
| 825 | 1061 | ||
| @@ -831,6 +1067,7 @@ static void asm_fref(ASMState *as, IRIns *ir) | |||
| 831 | 1067 | ||
| 832 | static void asm_strref(ASMState *as, IRIns *ir) | 1068 | static void asm_strref(ASMState *as, IRIns *ir) |
| 833 | { | 1069 | { |
| 1070 | #if LJ_32 | ||
| 834 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1071 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 835 | IRRef ref = ir->op2, refk = ir->op1; | 1072 | IRRef ref = ir->op2, refk = ir->op1; |
| 836 | int32_t ofs = (int32_t)sizeof(GCstr); | 1073 | int32_t ofs = (int32_t)sizeof(GCstr); |
| @@ -862,6 +1099,20 @@ static void asm_strref(ASMState *as, IRIns *ir) | |||
| 862 | else | 1099 | else |
| 863 | emit_dst(as, MIPSI_ADDU, dest, r, | 1100 | emit_dst(as, MIPSI_ADDU, dest, r, |
| 864 | ra_allock(as, ofs, rset_exclude(RSET_GPR, r))); | 1101 | ra_allock(as, ofs, rset_exclude(RSET_GPR, r))); |
| 1102 | #else | ||
| 1103 | RegSet allow = RSET_GPR; | ||
| 1104 | Reg dest = ra_dest(as, ir, allow); | ||
| 1105 | Reg base = ra_alloc1(as, ir->op1, allow); | ||
| 1106 | IRIns *irr = IR(ir->op2); | ||
| 1107 | int32_t ofs = sizeof(GCstr); | ||
| 1108 | rset_clear(allow, base); | ||
| 1109 | if (irref_isk(ir->op2) && checki16(ofs + irr->i)) { | ||
| 1110 | emit_tsi(as, MIPSI_DADDIU, dest, base, ofs + irr->i); | ||
| 1111 | } else { | ||
| 1112 | emit_tsi(as, MIPSI_DADDIU, dest, dest, ofs); | ||
| 1113 | emit_dst(as, MIPSI_DADDU, dest, base, ra_alloc1(as, ir->op2, allow)); | ||
| 1114 | } | ||
| 1115 | #endif | ||
| 865 | } | 1116 | } |
| 866 | 1117 | ||
| 867 | /* -- Loads and stores ---------------------------------------------------- */ | 1118 | /* -- Loads and stores ---------------------------------------------------- */ |
| @@ -875,7 +1126,7 @@ static MIPSIns asm_fxloadins(IRIns *ir) | |||
| 875 | case IRT_U16: return MIPSI_LHU; | 1126 | case IRT_U16: return MIPSI_LHU; |
| 876 | case IRT_NUM: lua_assert(!LJ_SOFTFP); return MIPSI_LDC1; | 1127 | case IRT_NUM: lua_assert(!LJ_SOFTFP); return MIPSI_LDC1; |
| 877 | case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_LWC1; | 1128 | case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_LWC1; |
| 878 | default: return MIPSI_LW; | 1129 | default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_LD : MIPSI_LW; |
| 879 | } | 1130 | } |
| 880 | } | 1131 | } |
| 881 | 1132 | ||
| @@ -886,7 +1137,7 @@ static MIPSIns asm_fxstoreins(IRIns *ir) | |||
| 886 | case IRT_I16: case IRT_U16: return MIPSI_SH; | 1137 | case IRT_I16: case IRT_U16: return MIPSI_SH; |
| 887 | case IRT_NUM: lua_assert(!LJ_SOFTFP); return MIPSI_SDC1; | 1138 | case IRT_NUM: lua_assert(!LJ_SOFTFP); return MIPSI_SDC1; |
| 888 | case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_SWC1; | 1139 | case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_SWC1; |
| 889 | default: return MIPSI_SW; | 1140 | default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_SD : MIPSI_SW; |
| 890 | } | 1141 | } |
| 891 | } | 1142 | } |
| 892 | 1143 | ||
| @@ -898,13 +1149,13 @@ static void asm_fload(ASMState *as, IRIns *ir) | |||
| 898 | int32_t ofs; | 1149 | int32_t ofs; |
| 899 | if (ir->op1 == REF_NIL) { | 1150 | if (ir->op1 == REF_NIL) { |
| 900 | idx = RID_JGL; | 1151 | idx = RID_JGL; |
| 901 | ofs = (ir->op2 << 2) - 32768; | 1152 | ofs = (ir->op2 << 2) - 32768 - GG_OFS(g); |
| 902 | } else { | 1153 | } else { |
| 903 | idx = ra_alloc1(as, ir->op1, RSET_GPR); | 1154 | idx = ra_alloc1(as, ir->op1, RSET_GPR); |
| 904 | if (ir->op2 == IRFL_TAB_ARRAY) { | 1155 | if (ir->op2 == IRFL_TAB_ARRAY) { |
| 905 | ofs = asm_fuseabase(as, ir->op1); | 1156 | ofs = asm_fuseabase(as, ir->op1); |
| 906 | if (ofs) { /* Turn the t->array load into an add for colocated arrays. */ | 1157 | if (ofs) { /* Turn the t->array load into an add for colocated arrays. */ |
| 907 | emit_tsi(as, MIPSI_ADDIU, dest, idx, ofs); | 1158 | emit_tsi(as, MIPSI_AADDIU, dest, idx, ofs); |
| 908 | return; | 1159 | return; |
| 909 | } | 1160 | } |
| 910 | } | 1161 | } |
| @@ -949,36 +1200,59 @@ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs) | |||
| 949 | 1200 | ||
| 950 | static void asm_ahuvload(ASMState *as, IRIns *ir) | 1201 | static void asm_ahuvload(ASMState *as, IRIns *ir) |
| 951 | { | 1202 | { |
| 952 | int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP); | 1203 | int hiop = (LJ_32 && LJ_SOFTFP && (ir+1)->o == IR_HIOP); |
| 953 | IRType t = hiop ? IRT_NUM : irt_type(ir->t); | ||
| 954 | Reg dest = RID_NONE, type = RID_TMP, idx; | 1204 | Reg dest = RID_NONE, type = RID_TMP, idx; |
| 955 | RegSet allow = RSET_GPR; | 1205 | RegSet allow = RSET_GPR; |
| 956 | int32_t ofs = 0; | 1206 | int32_t ofs = 0; |
| 957 | if (hiop && ra_used(ir+1)) { | 1207 | IRType1 t = ir->t; |
| 958 | type = ra_dest(as, ir+1, allow); | 1208 | if (hiop) { |
| 959 | rset_clear(allow, type); | 1209 | t.irt = IRT_NUM; |
| 1210 | if (ra_used(ir+1)) { | ||
| 1211 | type = ra_dest(as, ir+1, allow); | ||
| 1212 | rset_clear(allow, type); | ||
| 1213 | } | ||
| 960 | } | 1214 | } |
| 961 | if (ra_used(ir)) { | 1215 | if (ra_used(ir)) { |
| 962 | lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) || | 1216 | lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) || |
| 963 | irt_isint(ir->t) || irt_isaddr(ir->t)); | 1217 | irt_isint(ir->t) || irt_isaddr(ir->t)); |
| 964 | dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow); | 1218 | dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow); |
| 965 | rset_clear(allow, dest); | 1219 | rset_clear(allow, dest); |
| 1220 | #if LJ_64 | ||
| 1221 | if (irt_isaddr(t)) | ||
| 1222 | emit_tsml(as, MIPSI_DEXTM, dest, dest, 14, 0); | ||
| 1223 | else if (irt_isint(t)) | ||
| 1224 | emit_dta(as, MIPSI_SLL, dest, dest, 0); | ||
| 1225 | #endif | ||
| 966 | } | 1226 | } |
| 967 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | 1227 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); |
| 968 | rset_clear(allow, idx); | 1228 | rset_clear(allow, idx); |
| 969 | if (t == IRT_NUM) { | 1229 | if (irt_isnum(t)) { |
| 970 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); | 1230 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); |
| 971 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM); | 1231 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM); |
| 972 | } else { | 1232 | } else { |
| 973 | asm_guard(as, MIPSI_BNE, type, ra_allock(as, irt_toitype_(t), allow)); | 1233 | asm_guard(as, MIPSI_BNE, type, |
| 1234 | ra_allock(as, (int32_t)irt_toitype(t), allow)); | ||
| 974 | } | 1235 | } |
| 1236 | #if LJ_32 | ||
| 975 | if (ra_hasreg(dest)) { | 1237 | if (ra_hasreg(dest)) { |
| 976 | if (!LJ_SOFTFP && t == IRT_NUM) | 1238 | if (!LJ_SOFTFP && irt_isnum(t)) |
| 977 | emit_hsi(as, MIPSI_LDC1, dest, idx, ofs); | 1239 | emit_hsi(as, MIPSI_LDC1, dest, idx, ofs); |
| 978 | else | 1240 | else |
| 979 | emit_tsi(as, MIPSI_LW, dest, idx, ofs+(LJ_BE?4:0)); | 1241 | emit_tsi(as, MIPSI_LW, dest, idx, ofs+(LJ_BE?4:0)); |
| 980 | } | 1242 | } |
| 981 | emit_tsi(as, MIPSI_LW, type, idx, ofs+(LJ_BE?0:4)); | 1243 | emit_tsi(as, MIPSI_LW, type, idx, ofs+(LJ_BE?0:4)); |
| 1244 | #else | ||
| 1245 | if (ra_hasreg(dest)) { | ||
| 1246 | if (!LJ_SOFTFP && irt_isnum(t)) { | ||
| 1247 | emit_hsi(as, MIPSI_LDC1, dest, idx, ofs); | ||
| 1248 | dest = type; | ||
| 1249 | } | ||
| 1250 | } else { | ||
| 1251 | dest = type; | ||
| 1252 | } | ||
| 1253 | emit_dta(as, MIPSI_DSRA32, type, dest, 15); | ||
| 1254 | emit_tsi(as, MIPSI_LD, dest, idx, ofs); | ||
| 1255 | #endif | ||
| 982 | } | 1256 | } |
| 983 | 1257 | ||
| 984 | static void asm_ahustore(ASMState *as, IRIns *ir) | 1258 | static void asm_ahustore(ASMState *as, IRIns *ir) |
| @@ -990,103 +1264,159 @@ static void asm_ahustore(ASMState *as, IRIns *ir) | |||
| 990 | return; | 1264 | return; |
| 991 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { | 1265 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
| 992 | src = ra_alloc1(as, ir->op2, RSET_FPR); | 1266 | src = ra_alloc1(as, ir->op2, RSET_FPR); |
| 1267 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | ||
| 1268 | emit_hsi(as, MIPSI_SDC1, src, idx, ofs); | ||
| 993 | } else { | 1269 | } else { |
| 994 | int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP); | 1270 | #if LJ_32 |
| 995 | if (!irt_ispri(ir->t)) { | 1271 | if (!irt_ispri(ir->t)) { |
| 996 | src = ra_alloc1(as, ir->op2, allow); | 1272 | src = ra_alloc1(as, ir->op2, allow); |
| 997 | rset_clear(allow, src); | 1273 | rset_clear(allow, src); |
| 998 | } | 1274 | } |
| 999 | if (hiop) | 1275 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) |
| 1000 | type = ra_alloc1(as, (ir+1)->op2, allow); | 1276 | type = ra_alloc1(as, (ir+1)->op2, allow); |
| 1001 | else | 1277 | else |
| 1002 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 1278 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); |
| 1003 | rset_clear(allow, type); | 1279 | rset_clear(allow, type); |
| 1004 | } | 1280 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); |
| 1005 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | ||
| 1006 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { | ||
| 1007 | emit_hsi(as, MIPSI_SDC1, src, idx, ofs); | ||
| 1008 | } else { | ||
| 1009 | if (ra_hasreg(src)) | 1281 | if (ra_hasreg(src)) |
| 1010 | emit_tsi(as, MIPSI_SW, src, idx, ofs+(LJ_BE?4:0)); | 1282 | emit_tsi(as, MIPSI_SW, src, idx, ofs+(LJ_BE?4:0)); |
| 1011 | emit_tsi(as, MIPSI_SW, type, idx, ofs+(LJ_BE?0:4)); | 1283 | emit_tsi(as, MIPSI_SW, type, idx, ofs+(LJ_BE?0:4)); |
| 1284 | #else | ||
| 1285 | Reg tmp = RID_TMP; | ||
| 1286 | if (irt_ispri(ir->t)) { | ||
| 1287 | tmp = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); | ||
| 1288 | rset_clear(allow, tmp); | ||
| 1289 | } else { | ||
| 1290 | src = ra_alloc1(as, ir->op2, allow); | ||
| 1291 | rset_clear(allow, src); | ||
| 1292 | type = ra_allock(as, (int64_t)irt_toitype(ir->t) << 47, allow); | ||
| 1293 | rset_clear(allow, type); | ||
| 1294 | } | ||
| 1295 | idx = asm_fuseahuref(as, ir->op1, &ofs, allow); | ||
| 1296 | emit_tsi(as, MIPSI_SD, tmp, idx, ofs); | ||
| 1297 | if (ra_hasreg(src)) { | ||
| 1298 | if (irt_isinteger(ir->t)) { | ||
| 1299 | emit_dst(as, MIPSI_DADDU, tmp, tmp, type); | ||
| 1300 | emit_tsml(as, MIPSI_DEXT, tmp, src, 31, 0); | ||
| 1301 | } else { | ||
| 1302 | emit_dst(as, MIPSI_DADDU, tmp, src, type); | ||
| 1303 | } | ||
| 1304 | } | ||
| 1305 | #endif | ||
| 1012 | } | 1306 | } |
| 1013 | } | 1307 | } |
| 1014 | 1308 | ||
| 1015 | static void asm_sload(ASMState *as, IRIns *ir) | 1309 | static void asm_sload(ASMState *as, IRIns *ir) |
| 1016 | { | 1310 | { |
| 1017 | int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0); | ||
| 1018 | int hiop = (LJ_SOFTFP && (ir+1)->o == IR_HIOP); | ||
| 1019 | IRType t = hiop ? IRT_NUM : irt_type(ir->t); | ||
| 1020 | Reg dest = RID_NONE, type = RID_NONE, base; | 1311 | Reg dest = RID_NONE, type = RID_NONE, base; |
| 1021 | RegSet allow = RSET_GPR; | 1312 | RegSet allow = RSET_GPR; |
| 1313 | IRType1 t = ir->t; | ||
| 1314 | #if LJ_32 | ||
| 1315 | int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0); | ||
| 1316 | int hiop = (LJ_32 && LJ_SOFTFP && (ir+1)->o == IR_HIOP); | ||
| 1317 | if (hiop) | ||
| 1318 | t.irt = IRT_NUM; | ||
| 1319 | #else | ||
| 1320 | int32_t ofs = 8*((int32_t)ir->op1-2); | ||
| 1321 | #endif | ||
| 1022 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ | 1322 | lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ |
| 1023 | lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK)); | 1323 | lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK)); |
| 1024 | #if LJ_SOFTFP | 1324 | #if LJ_32 && LJ_SOFTFP |
| 1025 | lua_assert(!(ir->op2 & IRSLOAD_CONVERT)); /* Handled by LJ_SOFTFP SPLIT. */ | 1325 | lua_assert(!(ir->op2 & IRSLOAD_CONVERT)); /* Handled by LJ_SOFTFP SPLIT. */ |
| 1026 | if (hiop && ra_used(ir+1)) { | 1326 | if (hiop && ra_used(ir+1)) { |
| 1027 | type = ra_dest(as, ir+1, allow); | 1327 | type = ra_dest(as, ir+1, allow); |
| 1028 | rset_clear(allow, type); | 1328 | rset_clear(allow, type); |
| 1029 | } | 1329 | } |
| 1030 | #else | 1330 | #else |
| 1031 | if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(ir->t) && t == IRT_INT) { | 1331 | if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { |
| 1032 | dest = ra_scratch(as, RSET_FPR); | 1332 | dest = ra_scratch(as, RSET_FPR); |
| 1033 | asm_tointg(as, ir, dest); | 1333 | asm_tointg(as, ir, dest); |
| 1034 | t = IRT_NUM; /* Continue with a regular number type check. */ | 1334 | t.irt = IRT_NUM; /* Continue with a regular number type check. */ |
| 1035 | } else | 1335 | } else |
| 1036 | #endif | 1336 | #endif |
| 1037 | if (ra_used(ir)) { | 1337 | if (ra_used(ir)) { |
| 1038 | lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) || | 1338 | lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) || |
| 1039 | irt_isint(ir->t) || irt_isaddr(ir->t)); | 1339 | irt_isint(ir->t) || irt_isaddr(ir->t)); |
| 1040 | dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow); | 1340 | dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow); |
| 1041 | rset_clear(allow, dest); | 1341 | rset_clear(allow, dest); |
| 1042 | base = ra_alloc1(as, REF_BASE, allow); | 1342 | base = ra_alloc1(as, REF_BASE, allow); |
| 1043 | rset_clear(allow, base); | 1343 | rset_clear(allow, base); |
| 1044 | if (!LJ_SOFTFP && (ir->op2 & IRSLOAD_CONVERT)) { | 1344 | if (!LJ_SOFTFP && (ir->op2 & IRSLOAD_CONVERT)) { |
| 1045 | if (t == IRT_INT) { | 1345 | if (irt_isint(t)) { |
| 1046 | Reg tmp = ra_scratch(as, RSET_FPR); | 1346 | Reg tmp = ra_scratch(as, RSET_FPR); |
| 1047 | emit_tg(as, MIPSI_MFC1, dest, tmp); | 1347 | emit_tg(as, MIPSI_MFC1, dest, tmp); |
| 1048 | emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp); | 1348 | emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp); |
| 1049 | dest = tmp; | 1349 | dest = tmp; |
| 1050 | t = IRT_NUM; /* Check for original type. */ | 1350 | t.irt = IRT_NUM; /* Check for original type. */ |
| 1051 | } else { | 1351 | } else { |
| 1052 | Reg tmp = ra_scratch(as, RSET_GPR); | 1352 | Reg tmp = ra_scratch(as, RSET_GPR); |
| 1053 | emit_fg(as, MIPSI_CVT_D_W, dest, dest); | 1353 | emit_fg(as, MIPSI_CVT_D_W, dest, dest); |
| 1054 | emit_tg(as, MIPSI_MTC1, tmp, dest); | 1354 | emit_tg(as, MIPSI_MTC1, tmp, dest); |
| 1055 | dest = tmp; | 1355 | dest = tmp; |
| 1056 | t = IRT_INT; /* Check for original type. */ | 1356 | t.irt = IRT_INT; /* Check for original type. */ |
| 1057 | } | 1357 | } |
| 1058 | } | 1358 | } |
| 1359 | #if LJ_64 | ||
| 1360 | else if (irt_isaddr(t)) { | ||
| 1361 | /* Clear type from pointers. */ | ||
| 1362 | emit_tsml(as, MIPSI_DEXTM, dest, dest, 14, 0); | ||
| 1363 | } else if (irt_isint(t) && (ir->op2 & IRSLOAD_TYPECHECK)) { | ||
| 1364 | /* Sign-extend integers. */ | ||
| 1365 | emit_dta(as, MIPSI_SLL, dest, dest, 0); | ||
| 1366 | } | ||
| 1367 | #endif | ||
| 1059 | goto dotypecheck; | 1368 | goto dotypecheck; |
| 1060 | } | 1369 | } |
| 1061 | base = ra_alloc1(as, REF_BASE, allow); | 1370 | base = ra_alloc1(as, REF_BASE, allow); |
| 1062 | rset_clear(allow, base); | 1371 | rset_clear(allow, base); |
| 1063 | dotypecheck: | 1372 | dotypecheck: |
| 1373 | #if LJ_32 | ||
| 1064 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | 1374 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { |
| 1065 | if (ra_noreg(type)) { | 1375 | if (ra_noreg(type)) |
| 1066 | if (ofs < 256 && ra_hasreg(dest) && (dest & 1) == 0 && | 1376 | type = RID_TMP; |
| 1067 | rset_test((as->freeset & allow), dest+1)) { | 1377 | if (irt_isnum(t)) { |
| 1068 | type = dest+1; | ||
| 1069 | ra_modified(as, type); | ||
| 1070 | } else { | ||
| 1071 | type = RID_TMP; | ||
| 1072 | } | ||
| 1073 | } | ||
| 1074 | if (t == IRT_NUM) { | ||
| 1075 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); | 1378 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); |
| 1076 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM); | 1379 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM); |
| 1077 | } else { | 1380 | } else { |
| 1078 | Reg ktype = ra_allock(as, irt_toitype_(t), allow); | 1381 | Reg ktype = ra_allock(as, irt_toitype(t), allow); |
| 1079 | asm_guard(as, MIPSI_BNE, type, ktype); | 1382 | asm_guard(as, MIPSI_BNE, type, ktype); |
| 1080 | } | 1383 | } |
| 1081 | } | 1384 | } |
| 1082 | if (ra_hasreg(dest)) { | 1385 | if (ra_hasreg(dest)) { |
| 1083 | if (!LJ_SOFTFP && t == IRT_NUM) | 1386 | if (!LJ_SOFTFP && irt_isnum(t)) |
| 1084 | emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | 1387 | emit_hsi(as, MIPSI_LDC1, dest, base, ofs); |
| 1085 | else | 1388 | else |
| 1086 | emit_tsi(as, MIPSI_LW, dest, base, ofs ^ (LJ_BE?4:0)); | 1389 | emit_tsi(as, MIPSI_LW, dest, base, ofs ^ (LJ_BE?4:0)); |
| 1087 | } | 1390 | } |
| 1088 | if (ra_hasreg(type)) | 1391 | if (ra_hasreg(type)) |
| 1089 | emit_tsi(as, MIPSI_LW, type, base, ofs ^ (LJ_BE?0:4)); | 1392 | emit_tsi(as, MIPSI_LW, type, base, ofs ^ (LJ_BE?0:4)); |
| 1393 | #else | ||
| 1394 | if ((ir->op2 & IRSLOAD_TYPECHECK)) { | ||
| 1395 | type = dest < RID_MAX_GPR ? dest : RID_TMP; | ||
| 1396 | if (irt_ispri(t)) { | ||
| 1397 | asm_guard(as, MIPSI_BNE, type, | ||
| 1398 | ra_allock(as, ~((int64_t)~irt_toitype(t) << 47) , allow)); | ||
| 1399 | } else { | ||
| 1400 | if (irt_isnum(t)) { | ||
| 1401 | asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); | ||
| 1402 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)LJ_TISNUM); | ||
| 1403 | if (ra_hasreg(dest)) | ||
| 1404 | emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | ||
| 1405 | } else { | ||
| 1406 | asm_guard(as, MIPSI_BNE, RID_TMP, | ||
| 1407 | ra_allock(as, (int32_t)irt_toitype(t), allow)); | ||
| 1408 | } | ||
| 1409 | emit_dta(as, MIPSI_DSRA32, RID_TMP, type, 15); | ||
| 1410 | } | ||
| 1411 | emit_tsi(as, MIPSI_LD, type, base, ofs); | ||
| 1412 | } else if (ra_hasreg(dest)) { | ||
| 1413 | if (irt_isnum(t)) | ||
| 1414 | emit_hsi(as, MIPSI_LDC1, dest, base, ofs); | ||
| 1415 | else | ||
| 1416 | emit_tsi(as, irt_isint(t) ? MIPSI_LW : MIPSI_LD, dest, base, | ||
| 1417 | ofs ^ ((LJ_BE && irt_isint(t)) ? 4 : 0)); | ||
| 1418 | } | ||
| 1419 | #endif | ||
| 1090 | } | 1420 | } |
| 1091 | 1421 | ||
| 1092 | /* -- Allocations --------------------------------------------------------- */ | 1422 | /* -- Allocations --------------------------------------------------------- */ |
| @@ -1113,8 +1443,8 @@ static void asm_cnew(ASMState *as, IRIns *ir) | |||
| 1113 | /* Initialize immutable cdata object. */ | 1443 | /* Initialize immutable cdata object. */ |
| 1114 | if (ir->o == IR_CNEWI) { | 1444 | if (ir->o == IR_CNEWI) { |
| 1115 | RegSet allow = (RSET_GPR & ~RSET_SCRATCH); | 1445 | RegSet allow = (RSET_GPR & ~RSET_SCRATCH); |
| 1446 | #if LJ_32 | ||
| 1116 | int32_t ofs = sizeof(GCcdata); | 1447 | int32_t ofs = sizeof(GCcdata); |
| 1117 | lua_assert(sz == 4 || sz == 8); | ||
| 1118 | if (sz == 8) { | 1448 | if (sz == 8) { |
| 1119 | ofs += 4; | 1449 | ofs += 4; |
| 1120 | lua_assert((ir+1)->o == IR_HIOP); | 1450 | lua_assert((ir+1)->o == IR_HIOP); |
| @@ -1127,6 +1457,11 @@ static void asm_cnew(ASMState *as, IRIns *ir) | |||
| 1127 | if (ofs == sizeof(GCcdata)) break; | 1457 | if (ofs == sizeof(GCcdata)) break; |
| 1128 | ofs -= 4; if (LJ_BE) ir++; else ir--; | 1458 | ofs -= 4; if (LJ_BE) ir++; else ir--; |
| 1129 | } | 1459 | } |
| 1460 | #else | ||
| 1461 | emit_tsi(as, MIPSI_SD, ra_alloc1(as, ir->op2, allow), | ||
| 1462 | RID_RET, sizeof(GCcdata)); | ||
| 1463 | #endif | ||
| 1464 | lua_assert(sz == 4 || sz == 8); | ||
| 1130 | } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */ | 1465 | } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */ |
| 1131 | ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv]; | 1466 | ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv]; |
| 1132 | args[0] = ASMREF_L; /* lua_State *L */ | 1467 | args[0] = ASMREF_L; /* lua_State *L */ |
| @@ -1161,7 +1496,7 @@ static void asm_tbar(ASMState *as, IRIns *ir) | |||
| 1161 | Reg mark = ra_scratch(as, rset_exclude(RSET_GPR, tab)); | 1496 | Reg mark = ra_scratch(as, rset_exclude(RSET_GPR, tab)); |
| 1162 | Reg link = RID_TMP; | 1497 | Reg link = RID_TMP; |
| 1163 | MCLabel l_end = emit_label(as); | 1498 | MCLabel l_end = emit_label(as); |
| 1164 | emit_tsi(as, MIPSI_SW, link, tab, (int32_t)offsetof(GCtab, gclist)); | 1499 | emit_tsi(as, MIPSI_AS, link, tab, (int32_t)offsetof(GCtab, gclist)); |
| 1165 | emit_tsi(as, MIPSI_SB, mark, tab, (int32_t)offsetof(GCtab, marked)); | 1500 | emit_tsi(as, MIPSI_SB, mark, tab, (int32_t)offsetof(GCtab, marked)); |
| 1166 | emit_setgl(as, tab, gc.grayagain); | 1501 | emit_setgl(as, tab, gc.grayagain); |
| 1167 | emit_getgl(as, link, gc.grayagain); | 1502 | emit_getgl(as, link, gc.grayagain); |
| @@ -1184,7 +1519,7 @@ static void asm_obar(ASMState *as, IRIns *ir) | |||
| 1184 | args[0] = ASMREF_TMP1; /* global_State *g */ | 1519 | args[0] = ASMREF_TMP1; /* global_State *g */ |
| 1185 | args[1] = ir->op1; /* TValue *tv */ | 1520 | args[1] = ir->op1; /* TValue *tv */ |
| 1186 | asm_gencall(as, ci, args); | 1521 | asm_gencall(as, ci, args); |
| 1187 | emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); | 1522 | emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); |
| 1188 | obj = IR(ir->op1)->r; | 1523 | obj = IR(ir->op1)->r; |
| 1189 | tmp = ra_scratch(as, rset_exclude(RSET_GPR, obj)); | 1524 | tmp = ra_scratch(as, rset_exclude(RSET_GPR, obj)); |
| 1190 | emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end); | 1525 | emit_branch(as, MIPSI_BEQ, RID_TMP, RID_ZERO, l_end); |
| @@ -1230,8 +1565,9 @@ static void asm_fpmath(ASMState *as, IRIns *ir) | |||
| 1230 | 1565 | ||
| 1231 | static void asm_add(ASMState *as, IRIns *ir) | 1566 | static void asm_add(ASMState *as, IRIns *ir) |
| 1232 | { | 1567 | { |
| 1568 | IRType1 t = ir->t; | ||
| 1233 | #if !LJ_SOFTFP | 1569 | #if !LJ_SOFTFP |
| 1234 | if (irt_isnum(ir->t)) { | 1570 | if (irt_isnum(t)) { |
| 1235 | asm_fparith(as, ir, MIPSI_ADD_D); | 1571 | asm_fparith(as, ir, MIPSI_ADD_D); |
| 1236 | } else | 1572 | } else |
| 1237 | #endif | 1573 | #endif |
| @@ -1239,14 +1575,16 @@ static void asm_add(ASMState *as, IRIns *ir) | |||
| 1239 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1575 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 1240 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1576 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
| 1241 | if (irref_isk(ir->op2)) { | 1577 | if (irref_isk(ir->op2)) { |
| 1242 | int32_t k = IR(ir->op2)->i; | 1578 | intptr_t k = get_kval(IR(ir->op2)); |
| 1243 | if (checki16(k)) { | 1579 | if (checki16(k)) { |
| 1244 | emit_tsi(as, MIPSI_ADDIU, dest, left, k); | 1580 | emit_tsi(as, (LJ_64 && irt_is64(t)) ? MIPSI_DADDIU : MIPSI_ADDIU, dest, |
| 1581 | left, k); | ||
| 1245 | return; | 1582 | return; |
| 1246 | } | 1583 | } |
| 1247 | } | 1584 | } |
| 1248 | right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left)); | 1585 | right = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, left)); |
| 1249 | emit_dst(as, MIPSI_ADDU, dest, left, right); | 1586 | emit_dst(as, (LJ_64 && irt_is64(t)) ? MIPSI_DADDU : MIPSI_ADDU, dest, |
| 1587 | left, right); | ||
| 1250 | } | 1588 | } |
| 1251 | } | 1589 | } |
| 1252 | 1590 | ||
| @@ -1261,7 +1599,8 @@ static void asm_sub(ASMState *as, IRIns *ir) | |||
| 1261 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1599 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 1262 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 1600 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
| 1263 | right = (left >> 8); left &= 255; | 1601 | right = (left >> 8); left &= 255; |
| 1264 | emit_dst(as, MIPSI_SUBU, dest, left, right); | 1602 | emit_dst(as, (LJ_64 && irt_is64(ir->t)) ? MIPSI_DSUBU : MIPSI_SUBU, dest, |
| 1603 | left, right); | ||
| 1265 | } | 1604 | } |
| 1266 | } | 1605 | } |
| 1267 | 1606 | ||
| @@ -1276,13 +1615,49 @@ static void asm_mul(ASMState *as, IRIns *ir) | |||
| 1276 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1615 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 1277 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 1616 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
| 1278 | right = (left >> 8); left &= 255; | 1617 | right = (left >> 8); left &= 255; |
| 1279 | emit_dst(as, MIPSI_MUL, dest, left, right); | 1618 | if (LJ_64 && irt_is64(ir->t)) { |
| 1619 | emit_dst(as, MIPSI_MFLO, dest, 0, 0); | ||
| 1620 | emit_dst(as, MIPSI_DMULT, 0, left, right); | ||
| 1621 | } else { | ||
| 1622 | emit_dst(as, MIPSI_MUL, dest, left, right); | ||
| 1623 | } | ||
| 1280 | } | 1624 | } |
| 1281 | } | 1625 | } |
| 1282 | 1626 | ||
| 1283 | #define asm_div(as, ir) asm_fparith(as, ir, MIPSI_DIV_D) | 1627 | static void asm_mod(ASMState *as, IRIns *ir) |
| 1284 | #define asm_mod(as, ir) asm_callid(as, ir, IRCALL_lj_vm_modi) | 1628 | { |
| 1285 | #define asm_pow(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi) | 1629 | #if LJ_64 && LJ_HASFFI |
| 1630 | if (!irt_isint(ir->t)) | ||
| 1631 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : | ||
| 1632 | IRCALL_lj_carith_modu64); | ||
| 1633 | else | ||
| 1634 | #endif | ||
| 1635 | asm_callid(as, ir, IRCALL_lj_vm_modi); | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | #if !LJ_SOFTFP | ||
| 1639 | static void asm_pow(ASMState *as, IRIns *ir) | ||
| 1640 | { | ||
| 1641 | #if LJ_64 && LJ_HASFFI | ||
| 1642 | if (!irt_isnum(ir->t)) | ||
| 1643 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | ||
| 1644 | IRCALL_lj_carith_powu64); | ||
| 1645 | else | ||
| 1646 | #endif | ||
| 1647 | asm_callid(as, ir, IRCALL_lj_vm_powi); | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | static void asm_div(ASMState *as, IRIns *ir) | ||
| 1651 | { | ||
| 1652 | #if LJ_64 && LJ_HASFFI | ||
| 1653 | if (!irt_isnum(ir->t)) | ||
| 1654 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 : | ||
| 1655 | IRCALL_lj_carith_divu64); | ||
| 1656 | else | ||
| 1657 | #endif | ||
| 1658 | asm_fparith(as, ir, MIPSI_DIV_D); | ||
| 1659 | } | ||
| 1660 | #endif | ||
| 1286 | 1661 | ||
| 1287 | static void asm_neg(ASMState *as, IRIns *ir) | 1662 | static void asm_neg(ASMState *as, IRIns *ir) |
| 1288 | { | 1663 | { |
| @@ -1294,7 +1669,8 @@ static void asm_neg(ASMState *as, IRIns *ir) | |||
| 1294 | { | 1669 | { |
| 1295 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1670 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 1296 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1671 | Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
| 1297 | emit_dst(as, MIPSI_SUBU, dest, RID_ZERO, left); | 1672 | emit_dst(as, (LJ_64 && irt_is64(ir->t)) ? MIPSI_DSUBU : MIPSI_SUBU, dest, |
| 1673 | RID_ZERO, left); | ||
| 1298 | } | 1674 | } |
| 1299 | } | 1675 | } |
| 1300 | 1676 | ||
| @@ -1305,6 +1681,7 @@ static void asm_neg(ASMState *as, IRIns *ir) | |||
| 1305 | static void asm_arithov(ASMState *as, IRIns *ir) | 1681 | static void asm_arithov(ASMState *as, IRIns *ir) |
| 1306 | { | 1682 | { |
| 1307 | Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR); | 1683 | Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR); |
| 1684 | lua_assert(!irt_is64(ir->t)); | ||
| 1308 | if (irref_isk(ir->op2)) { | 1685 | if (irref_isk(ir->op2)) { |
| 1309 | int k = IR(ir->op2)->i; | 1686 | int k = IR(ir->op2)->i; |
| 1310 | if (ir->o == IR_SUBOV) k = -k; | 1687 | if (ir->o == IR_SUBOV) k = -k; |
| @@ -1352,7 +1729,7 @@ static void asm_mulov(ASMState *as, IRIns *ir) | |||
| 1352 | emit_dst(as, MIPSI_MULT, 0, left, right); | 1729 | emit_dst(as, MIPSI_MULT, 0, left, right); |
| 1353 | } | 1730 | } |
| 1354 | 1731 | ||
| 1355 | #if LJ_HASFFI | 1732 | #if LJ_32 && LJ_HASFFI |
| 1356 | static void asm_add64(ASMState *as, IRIns *ir) | 1733 | static void asm_add64(ASMState *as, IRIns *ir) |
| 1357 | { | 1734 | { |
| 1358 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1735 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| @@ -1454,6 +1831,7 @@ static void asm_bswap(ASMState *as, IRIns *ir) | |||
| 1454 | { | 1831 | { |
| 1455 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1832 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 1456 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); | 1833 | Reg left = ra_alloc1(as, ir->op1, RSET_GPR); |
| 1834 | #if LJ_32 | ||
| 1457 | if ((as->flags & JIT_F_MIPSXXR2)) { | 1835 | if ((as->flags & JIT_F_MIPSXXR2)) { |
| 1458 | emit_dta(as, MIPSI_ROTR, dest, RID_TMP, 16); | 1836 | emit_dta(as, MIPSI_ROTR, dest, RID_TMP, 16); |
| 1459 | emit_dst(as, MIPSI_WSBH, RID_TMP, 0, left); | 1837 | emit_dst(as, MIPSI_WSBH, RID_TMP, 0, left); |
| @@ -1469,6 +1847,15 @@ static void asm_bswap(ASMState *as, IRIns *ir) | |||
| 1469 | emit_dta(as, MIPSI_SRL, tmp, left, 24); | 1847 | emit_dta(as, MIPSI_SRL, tmp, left, 24); |
| 1470 | emit_dta(as, MIPSI_SLL, RID_TMP, left, 24); | 1848 | emit_dta(as, MIPSI_SLL, RID_TMP, left, 24); |
| 1471 | } | 1849 | } |
| 1850 | #else | ||
| 1851 | if (irt_is64(ir->t)) { | ||
| 1852 | emit_dst(as, MIPSI_DSHD, dest, 0, RID_TMP); | ||
| 1853 | emit_dst(as, MIPSI_DSBH, RID_TMP, 0, left); | ||
| 1854 | } else { | ||
| 1855 | emit_dta(as, MIPSI_ROTR, dest, RID_TMP, 16); | ||
| 1856 | emit_dst(as, MIPSI_WSBH, RID_TMP, 0, left); | ||
| 1857 | } | ||
| 1858 | #endif | ||
| 1472 | } | 1859 | } |
| 1473 | 1860 | ||
| 1474 | static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) | 1861 | static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) |
| @@ -1476,7 +1863,7 @@ static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) | |||
| 1476 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1863 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 1477 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); | 1864 | Reg right, left = ra_hintalloc(as, ir->op1, dest, RSET_GPR); |
| 1478 | if (irref_isk(ir->op2)) { | 1865 | if (irref_isk(ir->op2)) { |
| 1479 | int32_t k = IR(ir->op2)->i; | 1866 | intptr_t k = get_kval(IR(ir->op2)); |
| 1480 | if (checku16(k)) { | 1867 | if (checku16(k)) { |
| 1481 | emit_tsi(as, mik, dest, left, k); | 1868 | emit_tsi(as, mik, dest, left, k); |
| 1482 | return; | 1869 | return; |
| @@ -1494,11 +1881,14 @@ static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) | |||
| 1494 | { | 1881 | { |
| 1495 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1882 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| 1496 | if (irref_isk(ir->op2)) { /* Constant shifts. */ | 1883 | if (irref_isk(ir->op2)) { /* Constant shifts. */ |
| 1497 | uint32_t shift = (uint32_t)(IR(ir->op2)->i & 31); | 1884 | uint32_t shift = (uint32_t)IR(ir->op2)->i; |
| 1498 | emit_dta(as, mik, dest, ra_hintalloc(as, ir->op1, dest, RSET_GPR), shift); | 1885 | if (LJ_64 && irt_is64(ir->t)) mik |= (shift & 32) ? MIPSI_D32 : MIPSI_D; |
| 1886 | emit_dta(as, mik, dest, ra_hintalloc(as, ir->op1, dest, RSET_GPR), | ||
| 1887 | (shift & 31)); | ||
| 1499 | } else { | 1888 | } else { |
| 1500 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); | 1889 | Reg right, left = ra_alloc2(as, ir, RSET_GPR); |
| 1501 | right = (left >> 8); left &= 255; | 1890 | right = (left >> 8); left &= 255; |
| 1891 | if (LJ_64 && irt_is64(ir->t)) mi |= MIPSI_DV; | ||
| 1502 | emit_dst(as, mi, dest, right, left); /* Shift amount is in rs. */ | 1892 | emit_dst(as, mi, dest, right, left); /* Shift amount is in rs. */ |
| 1503 | } | 1893 | } |
| 1504 | } | 1894 | } |
| @@ -1510,7 +1900,7 @@ static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) | |||
| 1510 | 1900 | ||
| 1511 | static void asm_bror(ASMState *as, IRIns *ir) | 1901 | static void asm_bror(ASMState *as, IRIns *ir) |
| 1512 | { | 1902 | { |
| 1513 | if ((as->flags & JIT_F_MIPSXXR2)) { | 1903 | if (LJ_64 || (as->flags & JIT_F_MIPSXXR2)) { |
| 1514 | asm_bitshift(as, ir, MIPSI_ROTRV, MIPSI_ROTR); | 1904 | asm_bitshift(as, ir, MIPSI_ROTRV, MIPSI_ROTR); |
| 1515 | } else { | 1905 | } else { |
| 1516 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1906 | Reg dest = ra_dest(as, ir, RSET_GPR); |
| @@ -1529,7 +1919,7 @@ static void asm_bror(ASMState *as, IRIns *ir) | |||
| 1529 | } | 1919 | } |
| 1530 | } | 1920 | } |
| 1531 | 1921 | ||
| 1532 | #if LJ_SOFTFP | 1922 | #if LJ_32 && LJ_SOFTFP |
| 1533 | static void asm_sfpmin_max(ASMState *as, IRIns *ir) | 1923 | static void asm_sfpmin_max(ASMState *as, IRIns *ir) |
| 1534 | { | 1924 | { |
| 1535 | CCallInfo ci = lj_ir_callinfo[(IROp)ir->o == IR_MIN ? IRCALL_lj_vm_sfmin : IRCALL_lj_vm_sfmax]; | 1925 | CCallInfo ci = lj_ir_callinfo[(IROp)ir->o == IR_MIN ? IRCALL_lj_vm_sfmin : IRCALL_lj_vm_sfmax]; |
| @@ -1578,7 +1968,7 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax) | |||
| 1578 | 1968 | ||
| 1579 | /* -- Comparisons --------------------------------------------------------- */ | 1969 | /* -- Comparisons --------------------------------------------------------- */ |
| 1580 | 1970 | ||
| 1581 | #if LJ_SOFTFP | 1971 | #if LJ_32 && LJ_SOFTFP |
| 1582 | /* SFP comparisons. */ | 1972 | /* SFP comparisons. */ |
| 1583 | static void asm_sfpcomp(ASMState *as, IRIns *ir) | 1973 | static void asm_sfpcomp(ASMState *as, IRIns *ir) |
| 1584 | { | 1974 | { |
| @@ -1651,13 +2041,13 @@ static void asm_comp(ASMState *as, IRIns *ir) | |||
| 1651 | } else { | 2041 | } else { |
| 1652 | Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR); | 2042 | Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR); |
| 1653 | if (op == IR_ABC) op = IR_UGT; | 2043 | if (op == IR_ABC) op = IR_UGT; |
| 1654 | if ((op&4) == 0 && irref_isk(ir->op2) && IR(ir->op2)->i == 0) { | 2044 | if ((op&4) == 0 && irref_isk(ir->op2) && get_kval(IR(ir->op2)) == 0) { |
| 1655 | MIPSIns mi = (op&2) ? ((op&1) ? MIPSI_BLEZ : MIPSI_BGTZ) : | 2045 | MIPSIns mi = (op&2) ? ((op&1) ? MIPSI_BLEZ : MIPSI_BGTZ) : |
| 1656 | ((op&1) ? MIPSI_BLTZ : MIPSI_BGEZ); | 2046 | ((op&1) ? MIPSI_BLTZ : MIPSI_BGEZ); |
| 1657 | asm_guard(as, mi, left, 0); | 2047 | asm_guard(as, mi, left, 0); |
| 1658 | } else { | 2048 | } else { |
| 1659 | if (irref_isk(ir->op2)) { | 2049 | if (irref_isk(ir->op2)) { |
| 1660 | int32_t k = IR(ir->op2)->i; | 2050 | intptr_t k = get_kval(IR(ir->op2)); |
| 1661 | if ((op&2)) k++; | 2051 | if ((op&2)) k++; |
| 1662 | if (checki16(k)) { | 2052 | if (checki16(k)) { |
| 1663 | asm_guard(as, (op&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO); | 2053 | asm_guard(as, (op&1) ? MIPSI_BNE : MIPSI_BEQ, RID_TMP, RID_ZERO); |
| @@ -1676,7 +2066,8 @@ static void asm_comp(ASMState *as, IRIns *ir) | |||
| 1676 | 2066 | ||
| 1677 | static void asm_equal(ASMState *as, IRIns *ir) | 2067 | static void asm_equal(ASMState *as, IRIns *ir) |
| 1678 | { | 2068 | { |
| 1679 | Reg right, left = ra_alloc2(as, ir, (!LJ_SOFTFP && irt_isnum(ir->t)) ? RSET_FPR : RSET_GPR); | 2069 | Reg right, left = ra_alloc2(as, ir, (!LJ_SOFTFP && irt_isnum(ir->t)) ? |
| 2070 | RSET_FPR : RSET_GPR); | ||
| 1680 | right = (left >> 8); left &= 255; | 2071 | right = (left >> 8); left &= 255; |
| 1681 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { | 2072 | if (!LJ_SOFTFP && irt_isnum(ir->t)) { |
| 1682 | asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); | 2073 | asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); |
| @@ -1686,7 +2077,7 @@ static void asm_equal(ASMState *as, IRIns *ir) | |||
| 1686 | } | 2077 | } |
| 1687 | } | 2078 | } |
| 1688 | 2079 | ||
| 1689 | #if LJ_HASFFI | 2080 | #if LJ_32 && LJ_HASFFI |
| 1690 | /* 64 bit integer comparisons. */ | 2081 | /* 64 bit integer comparisons. */ |
| 1691 | static void asm_comp64(ASMState *as, IRIns *ir) | 2082 | static void asm_comp64(ASMState *as, IRIns *ir) |
| 1692 | { | 2083 | { |
| @@ -1728,7 +2119,7 @@ static void asm_comp64eq(ASMState *as, IRIns *ir) | |||
| 1728 | /* Hiword op of a split 64 bit op. Previous op must be the loword op. */ | 2119 | /* Hiword op of a split 64 bit op. Previous op must be the loword op. */ |
| 1729 | static void asm_hiop(ASMState *as, IRIns *ir) | 2120 | static void asm_hiop(ASMState *as, IRIns *ir) |
| 1730 | { | 2121 | { |
| 1731 | #if LJ_HASFFI || LJ_SOFTFP | 2122 | #if LJ_32 && (LJ_HASFFI || LJ_SOFTFP) |
| 1732 | /* HIOP is marked as a store because it needs its own DCE logic. */ | 2123 | /* HIOP is marked as a store because it needs its own DCE logic. */ |
| 1733 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ | 2124 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ |
| 1734 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; | 2125 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; |
| @@ -1832,36 +2223,42 @@ static void asm_stack_check(ASMState *as, BCReg topslot, | |||
| 1832 | Reg tmp, pbase = irp ? (ra_hasreg(irp->r) ? irp->r : RID_TMP) : RID_BASE; | 2223 | Reg tmp, pbase = irp ? (ra_hasreg(irp->r) ? irp->r : RID_TMP) : RID_BASE; |
| 1833 | ExitNo oldsnap = as->snapno; | 2224 | ExitNo oldsnap = as->snapno; |
| 1834 | rset_clear(allow, pbase); | 2225 | rset_clear(allow, pbase); |
| 2226 | #if LJ_32 | ||
| 1835 | tmp = allow ? rset_pickbot(allow) : | 2227 | tmp = allow ? rset_pickbot(allow) : |
| 1836 | (pbase == RID_RETHI ? RID_RETLO : RID_RETHI); | 2228 | (pbase == RID_RETHI ? RID_RETLO : RID_RETHI); |
| 2229 | #else | ||
| 2230 | tmp = allow ? rset_pickbot(allow) : RID_RET; | ||
| 2231 | #endif | ||
| 1837 | as->snapno = exitno; | 2232 | as->snapno = exitno; |
| 1838 | asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO); | 2233 | asm_guard(as, MIPSI_BNE, RID_TMP, RID_ZERO); |
| 1839 | as->snapno = oldsnap; | 2234 | as->snapno = oldsnap; |
| 1840 | if (allow == RSET_EMPTY) /* Restore temp. register. */ | 2235 | if (allow == RSET_EMPTY) /* Restore temp. register. */ |
| 1841 | emit_tsi(as, MIPSI_LW, tmp, RID_SP, 0); | 2236 | emit_tsi(as, MIPSI_AL, tmp, RID_SP, 0); |
| 1842 | else | 2237 | else |
| 1843 | ra_modified(as, tmp); | 2238 | ra_modified(as, tmp); |
| 1844 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)(8*topslot)); | 2239 | emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)(8*topslot)); |
| 1845 | emit_dst(as, MIPSI_SUBU, RID_TMP, tmp, pbase); | 2240 | emit_dst(as, MIPSI_ASUBU, RID_TMP, tmp, pbase); |
| 1846 | emit_tsi(as, MIPSI_LW, tmp, tmp, offsetof(lua_State, maxstack)); | 2241 | emit_tsi(as, MIPSI_AL, tmp, tmp, offsetof(lua_State, maxstack)); |
| 1847 | if (pbase == RID_TMP) | 2242 | if (pbase == RID_TMP) |
| 1848 | emit_getgl(as, RID_TMP, jit_base); | 2243 | emit_getgl(as, RID_TMP, jit_base); |
| 1849 | emit_getgl(as, tmp, cur_L); | 2244 | emit_getgl(as, tmp, cur_L); |
| 1850 | if (allow == RSET_EMPTY) /* Spill temp. register. */ | 2245 | if (allow == RSET_EMPTY) /* Spill temp. register. */ |
| 1851 | emit_tsi(as, MIPSI_SW, tmp, RID_SP, 0); | 2246 | emit_tsi(as, MIPSI_AS, tmp, RID_SP, 0); |
| 1852 | } | 2247 | } |
| 1853 | 2248 | ||
| 1854 | /* Restore Lua stack from on-trace state. */ | 2249 | /* Restore Lua stack from on-trace state. */ |
| 1855 | static void asm_stack_restore(ASMState *as, SnapShot *snap) | 2250 | static void asm_stack_restore(ASMState *as, SnapShot *snap) |
| 1856 | { | 2251 | { |
| 1857 | SnapEntry *map = &as->T->snapmap[snap->mapofs]; | 2252 | SnapEntry *map = &as->T->snapmap[snap->mapofs]; |
| 1858 | SnapEntry *flinks = &as->T->snapmap[snap_nextofs(as->T, snap)-1]; | 2253 | #if LJ_32 || defined(LUA_USE_ASSERT) |
| 2254 | SnapEntry *flinks = &as->T->snapmap[snap_nextofs(as->T, snap)-1-LJ_FR2]; | ||
| 2255 | #endif | ||
| 1859 | MSize n, nent = snap->nent; | 2256 | MSize n, nent = snap->nent; |
| 1860 | /* Store the value of all modified slots to the Lua stack. */ | 2257 | /* Store the value of all modified slots to the Lua stack. */ |
| 1861 | for (n = 0; n < nent; n++) { | 2258 | for (n = 0; n < nent; n++) { |
| 1862 | SnapEntry sn = map[n]; | 2259 | SnapEntry sn = map[n]; |
| 1863 | BCReg s = snap_slot(sn); | 2260 | BCReg s = snap_slot(sn); |
| 1864 | int32_t ofs = 8*((int32_t)s-1); | 2261 | int32_t ofs = 8*((int32_t)s-1-LJ_FR2); |
| 1865 | IRRef ref = snap_ref(sn); | 2262 | IRRef ref = snap_ref(sn); |
| 1866 | IRIns *ir = IR(ref); | 2263 | IRIns *ir = IR(ref); |
| 1867 | if ((sn & SNAP_NORESTORE)) | 2264 | if ((sn & SNAP_NORESTORE)) |
| @@ -1881,8 +2278,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
| 1881 | emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs); | 2278 | emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs); |
| 1882 | #endif | 2279 | #endif |
| 1883 | } else { | 2280 | } else { |
| 1884 | Reg type; | 2281 | #if LJ_32 |
| 1885 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); | 2282 | RegSet allow = rset_exclude(RSET_GPR, RID_BASE); |
| 2283 | Reg type; | ||
| 1886 | lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t)); | 2284 | lua_assert(irt_ispri(ir->t) || irt_isaddr(ir->t) || irt_isinteger(ir->t)); |
| 1887 | if (!irt_ispri(ir->t)) { | 2285 | if (!irt_ispri(ir->t)) { |
| 1888 | Reg src = ra_alloc1(as, ref, allow); | 2286 | Reg src = ra_alloc1(as, ref, allow); |
| @@ -1900,6 +2298,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
| 1900 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 2298 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); |
| 1901 | } | 2299 | } |
| 1902 | emit_tsi(as, MIPSI_SW, type, RID_BASE, ofs+(LJ_BE?0:4)); | 2300 | emit_tsi(as, MIPSI_SW, type, RID_BASE, ofs+(LJ_BE?0:4)); |
| 2301 | #else | ||
| 2302 | asm_tvstore64(as, RID_BASE, ofs, ref); | ||
| 2303 | #endif | ||
| 1903 | } | 2304 | } |
| 1904 | checkmclim(as); | 2305 | checkmclim(as); |
| 1905 | } | 2306 | } |
| @@ -1923,7 +2324,7 @@ static void asm_gc_check(ASMState *as) | |||
| 1923 | args[0] = ASMREF_TMP1; /* global_State *g */ | 2324 | args[0] = ASMREF_TMP1; /* global_State *g */ |
| 1924 | args[1] = ASMREF_TMP2; /* MSize steps */ | 2325 | args[1] = ASMREF_TMP2; /* MSize steps */ |
| 1925 | asm_gencall(as, ci, args); | 2326 | asm_gencall(as, ci, args); |
| 1926 | emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); | 2327 | emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); |
| 1927 | tmp = ra_releasetmp(as, ASMREF_TMP2); | 2328 | tmp = ra_releasetmp(as, ASMREF_TMP2); |
| 1928 | emit_loadi(as, tmp, as->gcsteps); | 2329 | emit_loadi(as, tmp, as->gcsteps); |
| 1929 | /* Jump around GC step if GC total < GC threshold. */ | 2330 | /* Jump around GC step if GC total < GC threshold. */ |
| @@ -1998,7 +2399,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk) | |||
| 1998 | MCode *target = lnk ? traceref(as->J,lnk)->mcode : (MCode *)lj_vm_exit_interp; | 2399 | MCode *target = lnk ? traceref(as->J,lnk)->mcode : (MCode *)lj_vm_exit_interp; |
| 1999 | int32_t spadj = as->T->spadjust; | 2400 | int32_t spadj = as->T->spadjust; |
| 2000 | MCode *p = as->mctop-1; | 2401 | MCode *p = as->mctop-1; |
| 2001 | *p = spadj ? (MIPSI_ADDIU|MIPSF_T(RID_SP)|MIPSF_S(RID_SP)|spadj) : MIPSI_NOP; | 2402 | *p = spadj ? (MIPSI_AADDIU|MIPSF_T(RID_SP)|MIPSF_S(RID_SP)|spadj) : MIPSI_NOP; |
| 2002 | p[-1] = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu); | 2403 | p[-1] = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu); |
| 2003 | } | 2404 | } |
| 2004 | 2405 | ||
| @@ -2016,9 +2417,14 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
| 2016 | { | 2417 | { |
| 2017 | IRRef args[CCI_NARGS_MAX*2]; | 2418 | IRRef args[CCI_NARGS_MAX*2]; |
| 2018 | uint32_t i, nargs = CCI_XNARGS(ci); | 2419 | uint32_t i, nargs = CCI_XNARGS(ci); |
| 2420 | #if LJ_32 | ||
| 2019 | int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; | 2421 | int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; |
| 2422 | #else | ||
| 2423 | int nslots = 0, ngpr = REGARG_NUMGPR; | ||
| 2424 | #endif | ||
| 2020 | asm_collectargs(as, ir, ci, args); | 2425 | asm_collectargs(as, ir, ci, args); |
| 2021 | for (i = 0; i < nargs; i++) { | 2426 | for (i = 0; i < nargs; i++) { |
| 2427 | #if LJ_32 | ||
| 2022 | if (!LJ_SOFTFP && args[i] && irt_isfp(IR(args[i])->t) && | 2428 | if (!LJ_SOFTFP && args[i] && irt_isfp(IR(args[i])->t) && |
| 2023 | nfpr > 0 && !(ci->flags & CCI_VARARG)) { | 2429 | nfpr > 0 && !(ci->flags & CCI_VARARG)) { |
| 2024 | nfpr--; | 2430 | nfpr--; |
| @@ -2031,6 +2437,9 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
| 2031 | nfpr = 0; | 2437 | nfpr = 0; |
| 2032 | if (ngpr > 0) ngpr--; else nslots++; | 2438 | if (ngpr > 0) ngpr--; else nslots++; |
| 2033 | } | 2439 | } |
| 2440 | #else | ||
| 2441 | if (ngpr > 0) ngpr--; else nslots += 2; | ||
| 2442 | #endif | ||
| 2034 | } | 2443 | } |
| 2035 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ | 2444 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ |
| 2036 | as->evenspill = nslots; | 2445 | as->evenspill = nslots; |
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 | ||
diff --git a/src/lj_jit.h b/src/lj_jit.h index ddcb576c..92054e3d 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h | |||
| @@ -337,6 +337,10 @@ enum { | |||
| 337 | #endif | 337 | #endif |
| 338 | #if LJ_TARGET_MIPS | 338 | #if LJ_TARGET_MIPS |
| 339 | LJ_K64_2P31, /* 2^31 */ | 339 | LJ_K64_2P31, /* 2^31 */ |
| 340 | #if LJ_64 | ||
| 341 | LJ_K64_2P63, /* 2^63 */ | ||
| 342 | LJ_K64_M2P64, /* -2^64 */ | ||
| 343 | #endif | ||
| 340 | #endif | 344 | #endif |
| 341 | LJ_K64__MAX, | 345 | LJ_K64__MAX, |
| 342 | }; | 346 | }; |
| @@ -352,6 +356,10 @@ enum { | |||
| 352 | #if LJ_TARGET_PPC || LJ_TARGET_MIPS | 356 | #if LJ_TARGET_PPC || LJ_TARGET_MIPS |
| 353 | LJ_K32_2P31, /* 2^31 */ | 357 | LJ_K32_2P31, /* 2^31 */ |
| 354 | #endif | 358 | #endif |
| 359 | #if LJ_TARGET_MIPS64 | ||
| 360 | LJ_K32_2P63, /* 2^63 */ | ||
| 361 | LJ_K32_M2P64, /* -2^64 */ | ||
| 362 | #endif | ||
| 355 | LJ_K32__MAX | 363 | LJ_K32__MAX |
| 356 | }; | 364 | }; |
| 357 | 365 | ||
diff --git a/src/lj_mcode.c b/src/lj_mcode.c index a33a4c5d..0f29a3ce 100644 --- a/src/lj_mcode.c +++ b/src/lj_mcode.c | |||
| @@ -206,7 +206,7 @@ static void mcode_protect(jit_State *J, int prot) | |||
| 206 | 206 | ||
| 207 | #if LJ_TARGET_X64 | 207 | #if LJ_TARGET_X64 |
| 208 | #define mcode_validptr(p) ((p) && (uintptr_t)(p) < (uintptr_t)1<<47) | 208 | #define mcode_validptr(p) ((p) && (uintptr_t)(p) < (uintptr_t)1<<47) |
| 209 | #elif LJ_TARGET_ARM64 | 209 | #elif LJ_TARGET_ARM64 || LJ_TARGET_MIPS64 |
| 210 | /* We have no clue about the valid VA range. It could be 39 - 52 bits. */ | 210 | /* We have no clue about the valid VA range. It could be 39 - 52 bits. */ |
| 211 | #define mcode_validptr(p) (p) | 211 | #define mcode_validptr(p) (p) |
| 212 | #else | 212 | #else |
| @@ -224,8 +224,8 @@ static void *mcode_alloc(jit_State *J, size_t sz) | |||
| 224 | */ | 224 | */ |
| 225 | #if LJ_TARGET_MIPS | 225 | #if LJ_TARGET_MIPS |
| 226 | /* Use the middle of the 256MB-aligned region. */ | 226 | /* Use the middle of the 256MB-aligned region. */ |
| 227 | uintptr_t target = ((uintptr_t)(void *)lj_vm_exit_handler & 0xf0000000u) + | 227 | uintptr_t target = ((uintptr_t)(void *)lj_vm_exit_handler & |
| 228 | 0x08000000u; | 228 | ~(uintptr_t)0x0fffffffu) + 0x08000000u; |
| 229 | #else | 229 | #else |
| 230 | uintptr_t target = (uintptr_t)(void *)lj_vm_exit_handler & ~(uintptr_t)0xffff; | 230 | uintptr_t target = (uintptr_t)(void *)lj_vm_exit_handler & ~(uintptr_t)0xffff; |
| 231 | #endif | 231 | #endif |
diff --git a/src/lj_snap.c b/src/lj_snap.c index 2eb40a8d..bb063c2b 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c | |||
| @@ -723,8 +723,9 @@ static void snap_restoredata(GCtrace *T, ExitState *ex, | |||
| 723 | #else | 723 | #else |
| 724 | if (LJ_BE && sz == 4) src++; | 724 | if (LJ_BE && sz == 4) src++; |
| 725 | #endif | 725 | #endif |
| 726 | } | 726 | } else |
| 727 | #endif | 727 | #endif |
| 728 | if (LJ_64 && LJ_BE && sz == 4) src++; | ||
| 728 | } | 729 | } |
| 729 | } | 730 | } |
| 730 | lua_assert(sz == 1 || sz == 2 || sz == 4 || sz == 8); | 731 | lua_assert(sz == 1 || sz == 2 || sz == 4 || sz == 8); |
diff --git a/src/lj_target_mips.h b/src/lj_target_mips.h index 1b061943..740687b3 100644 --- a/src/lj_target_mips.h +++ b/src/lj_target_mips.h | |||
| @@ -81,7 +81,7 @@ enum { | |||
| 81 | RID2RSET(RID_SYS1)|RID2RSET(RID_SYS2)|RID2RSET(RID_JGL)|RID2RSET(RID_GP)) | 81 | RID2RSET(RID_SYS1)|RID2RSET(RID_SYS2)|RID2RSET(RID_JGL)|RID2RSET(RID_GP)) |
| 82 | #define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) - RSET_FIXED) | 82 | #define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) - RSET_FIXED) |
| 83 | #if LJ_SOFTFP | 83 | #if LJ_SOFTFP |
| 84 | #define RSET_FPR 0 | 84 | #define RSET_FPR 0 |
| 85 | #else | 85 | #else |
| 86 | #if LJ_32 | 86 | #if LJ_32 |
| 87 | #define RSET_FPR \ | 87 | #define RSET_FPR \ |
| @@ -90,11 +90,11 @@ enum { | |||
| 90 | RID2RSET(RID_F16)|RID2RSET(RID_F18)|RID2RSET(RID_F20)|RID2RSET(RID_F22)|\ | 90 | RID2RSET(RID_F16)|RID2RSET(RID_F18)|RID2RSET(RID_F20)|RID2RSET(RID_F22)|\ |
| 91 | RID2RSET(RID_F24)|RID2RSET(RID_F26)|RID2RSET(RID_F28)|RID2RSET(RID_F30)) | 91 | RID2RSET(RID_F24)|RID2RSET(RID_F26)|RID2RSET(RID_F28)|RID2RSET(RID_F30)) |
| 92 | #else | 92 | #else |
| 93 | #define RSET_FPR RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR) | 93 | #define RSET_FPR RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR) |
| 94 | #endif | 94 | #endif |
| 95 | #endif | 95 | #endif |
| 96 | #define RSET_ALL (RSET_GPR|RSET_FPR) | 96 | #define RSET_ALL (RSET_GPR|RSET_FPR) |
| 97 | #define RSET_INIT RSET_ALL | 97 | #define RSET_INIT RSET_ALL |
| 98 | 98 | ||
| 99 | #define RSET_SCRATCH_GPR \ | 99 | #define RSET_SCRATCH_GPR \ |
| 100 | (RSET_RANGE(RID_R1, RID_R15+1)|\ | 100 | (RSET_RANGE(RID_R1, RID_R15+1)|\ |
| @@ -192,8 +192,12 @@ static LJ_AINLINE uint32_t *exitstub_trace_addr_(uint32_t *p) | |||
| 192 | #define MIPSF_F(r) ((r) << 6) | 192 | #define MIPSF_F(r) ((r) << 6) |
| 193 | #define MIPSF_A(n) ((n) << 6) | 193 | #define MIPSF_A(n) ((n) << 6) |
| 194 | #define MIPSF_M(n) ((n) << 11) | 194 | #define MIPSF_M(n) ((n) << 11) |
| 195 | #define MIPSF_L(n) ((n) << 6) | ||
| 195 | 196 | ||
| 196 | typedef enum MIPSIns { | 197 | typedef enum MIPSIns { |
| 198 | MIPSI_D = 0x38, | ||
| 199 | MIPSI_DV = 0x10, | ||
| 200 | MIPSI_D32 = 0x3c, | ||
| 197 | /* Integer instructions. */ | 201 | /* Integer instructions. */ |
| 198 | MIPSI_MOVE = 0x00000025, | 202 | MIPSI_MOVE = 0x00000025, |
| 199 | MIPSI_NOP = 0x00000000, | 203 | MIPSI_NOP = 0x00000000, |
| @@ -202,22 +206,27 @@ typedef enum MIPSIns { | |||
| 202 | MIPSI_LU = 0x34000000, | 206 | MIPSI_LU = 0x34000000, |
| 203 | MIPSI_LUI = 0x3c000000, | 207 | MIPSI_LUI = 0x3c000000, |
| 204 | 208 | ||
| 205 | MIPSI_ADDIU = 0x24000000, | 209 | MIPSI_AND = 0x00000024, |
| 206 | MIPSI_ANDI = 0x30000000, | 210 | MIPSI_ANDI = 0x30000000, |
| 211 | MIPSI_OR = 0x00000025, | ||
| 207 | MIPSI_ORI = 0x34000000, | 212 | MIPSI_ORI = 0x34000000, |
| 213 | MIPSI_XOR = 0x00000026, | ||
| 208 | MIPSI_XORI = 0x38000000, | 214 | MIPSI_XORI = 0x38000000, |
| 215 | MIPSI_NOR = 0x00000027, | ||
| 216 | |||
| 217 | MIPSI_SLT = 0x0000002a, | ||
| 218 | MIPSI_SLTU = 0x0000002b, | ||
| 209 | MIPSI_SLTI = 0x28000000, | 219 | MIPSI_SLTI = 0x28000000, |
| 210 | MIPSI_SLTIU = 0x2c000000, | 220 | MIPSI_SLTIU = 0x2c000000, |
| 211 | 221 | ||
| 212 | MIPSI_ADDU = 0x00000021, | 222 | MIPSI_ADDU = 0x00000021, |
| 223 | MIPSI_ADDIU = 0x24000000, | ||
| 224 | MIPSI_SUB = 0x00000022, | ||
| 213 | MIPSI_SUBU = 0x00000023, | 225 | MIPSI_SUBU = 0x00000023, |
| 214 | MIPSI_MUL = 0x70000002, | 226 | MIPSI_MUL = 0x70000002, |
| 215 | MIPSI_AND = 0x00000024, | 227 | MIPSI_DIV = 0x0000001a, |
| 216 | MIPSI_OR = 0x00000025, | 228 | MIPSI_DIVU = 0x0000001b, |
| 217 | MIPSI_XOR = 0x00000026, | 229 | |
| 218 | MIPSI_NOR = 0x00000027, | ||
| 219 | MIPSI_SLT = 0x0000002a, | ||
| 220 | MIPSI_SLTU = 0x0000002b, | ||
| 221 | MIPSI_MOVZ = 0x0000000a, | 230 | MIPSI_MOVZ = 0x0000000a, |
| 222 | MIPSI_MOVN = 0x0000000b, | 231 | MIPSI_MOVN = 0x0000000b, |
| 223 | MIPSI_MFHI = 0x00000010, | 232 | MIPSI_MFHI = 0x00000010, |
| @@ -228,14 +237,18 @@ typedef enum MIPSIns { | |||
| 228 | MIPSI_SRL = 0x00000002, | 237 | MIPSI_SRL = 0x00000002, |
| 229 | MIPSI_SRA = 0x00000003, | 238 | MIPSI_SRA = 0x00000003, |
| 230 | MIPSI_ROTR = 0x00200002, /* MIPSXXR2 */ | 239 | MIPSI_ROTR = 0x00200002, /* MIPSXXR2 */ |
| 240 | MIPSI_DROTR = 0x0020003a, | ||
| 241 | MIPSI_DROTR32 = 0x0020003e, | ||
| 231 | MIPSI_SLLV = 0x00000004, | 242 | MIPSI_SLLV = 0x00000004, |
| 232 | MIPSI_SRLV = 0x00000006, | 243 | MIPSI_SRLV = 0x00000006, |
| 233 | MIPSI_SRAV = 0x00000007, | 244 | MIPSI_SRAV = 0x00000007, |
| 234 | MIPSI_ROTRV = 0x00000046, /* MIPSXXR2 */ | 245 | MIPSI_ROTRV = 0x00000046, /* MIPSXXR2 */ |
| 246 | MIPSI_DROTRV = 0x00000056, | ||
| 235 | 247 | ||
| 236 | MIPSI_SEB = 0x7c000420, /* MIPSXXR2 */ | 248 | MIPSI_SEB = 0x7c000420, /* MIPSXXR2 */ |
| 237 | MIPSI_SEH = 0x7c000620, /* MIPSXXR2 */ | 249 | MIPSI_SEH = 0x7c000620, /* MIPSXXR2 */ |
| 238 | MIPSI_WSBH = 0x7c0000a0, /* MIPSXXR2 */ | 250 | MIPSI_WSBH = 0x7c0000a0, /* MIPSXXR2 */ |
| 251 | MIPSI_DSBH = 0x7c0000a4, | ||
| 239 | 252 | ||
| 240 | MIPSI_B = 0x10000000, | 253 | MIPSI_B = 0x10000000, |
| 241 | MIPSI_J = 0x08000000, | 254 | MIPSI_J = 0x08000000, |
| @@ -253,7 +266,9 @@ typedef enum MIPSIns { | |||
| 253 | 266 | ||
| 254 | /* Load/store instructions. */ | 267 | /* Load/store instructions. */ |
| 255 | MIPSI_LW = 0x8c000000, | 268 | MIPSI_LW = 0x8c000000, |
| 269 | MIPSI_LD = 0xdc000000, | ||
| 256 | MIPSI_SW = 0xac000000, | 270 | MIPSI_SW = 0xac000000, |
| 271 | MIPSI_SD = 0xfc000000, | ||
| 257 | MIPSI_LB = 0x80000000, | 272 | MIPSI_LB = 0x80000000, |
| 258 | MIPSI_SB = 0xa0000000, | 273 | MIPSI_SB = 0xa0000000, |
| 259 | MIPSI_LH = 0x84000000, | 274 | MIPSI_LH = 0x84000000, |
| @@ -266,13 +281,48 @@ typedef enum MIPSIns { | |||
| 266 | MIPSI_SDC1 = 0xf4000000, | 281 | MIPSI_SDC1 = 0xf4000000, |
| 267 | 282 | ||
| 268 | /* MIPS64 instructions. */ | 283 | /* MIPS64 instructions. */ |
| 269 | MIPSI_DSLL = 0x00000038, | 284 | MIPSI_DADD = 0x0000002c, |
| 270 | MIPSI_LD = 0xdc000000, | 285 | MIPSI_DADDI = 0x60000000, |
| 286 | MIPSI_DADDU = 0x0000002d, | ||
| 271 | MIPSI_DADDIU = 0x64000000, | 287 | MIPSI_DADDIU = 0x64000000, |
| 272 | MIPSI_SD = 0xfc000000, | 288 | MIPSI_DSUB = 0x0000002e, |
| 273 | MIPSI_DMFC1 = 0x44200000, | 289 | MIPSI_DSUBU = 0x0000002f, |
| 290 | MIPSI_DDIV = 0x0000001e, | ||
| 291 | MIPSI_DDIVU = 0x0000001f, | ||
| 292 | MIPSI_DMULT = 0x0000001c, | ||
| 293 | MIPSI_DMULTU = 0x0000001d, | ||
| 294 | |||
| 295 | MIPSI_DSLL = 0x00000038, | ||
| 296 | MIPSI_DSRL = 0x0000003a, | ||
| 297 | MIPSI_DSLLV = 0x00000014, | ||
| 298 | MIPSI_DSRLV = 0x00000016, | ||
| 299 | MIPSI_DSRA = 0x0000003b, | ||
| 300 | MIPSI_DSRAV = 0x00000017, | ||
| 274 | MIPSI_DSRA32 = 0x0000003f, | 301 | MIPSI_DSRA32 = 0x0000003f, |
| 275 | MIPSI_MFHC1 = 0x44600000, | 302 | MIPSI_DSLL32 = 0x0000003c, |
| 303 | MIPSI_DSRL32 = 0x0000003e, | ||
| 304 | MIPSI_DSHD = 0x7c000164, | ||
| 305 | |||
| 306 | MIPSI_AADDU = LJ_32 ? MIPSI_ADDU : MIPSI_DADDU, | ||
| 307 | MIPSI_AADDIU = LJ_32 ? MIPSI_ADDIU : MIPSI_DADDIU, | ||
| 308 | MIPSI_ASUBU = LJ_32 ? MIPSI_SUBU : MIPSI_DSUBU, | ||
| 309 | MIPSI_AL = LJ_32 ? MIPSI_LW : MIPSI_LD, | ||
| 310 | MIPSI_AS = LJ_32 ? MIPSI_SW : MIPSI_SD, | ||
| 311 | |||
| 312 | /* Extract/insert instructions. */ | ||
| 313 | MIPSI_DEXTM = 0x7c000001, | ||
| 314 | MIPSI_DEXTU = 0x7c000002, | ||
| 315 | MIPSI_DEXT = 0x7c000003, | ||
| 316 | MIPSI_DINSM = 0x7c000005, | ||
| 317 | MIPSI_DINSU = 0x7c000006, | ||
| 318 | MIPSI_DINS = 0x7c000007, | ||
| 319 | |||
| 320 | MIPSI_RINT_D = 0x4620001a, | ||
| 321 | MIPSI_RINT_S = 0x4600001a, | ||
| 322 | MIPSI_RINT = 0x4400001a, | ||
| 323 | MIPSI_FLOOR_D = 0x4620000b, | ||
| 324 | MIPSI_CEIL_D = 0x4620000a, | ||
| 325 | MIPSI_ROUND_D = 0x46200008, | ||
| 276 | 326 | ||
| 277 | /* FP instructions. */ | 327 | /* FP instructions. */ |
| 278 | MIPSI_MOV_S = 0x46000006, | 328 | MIPSI_MOV_S = 0x46000006, |
| @@ -298,24 +348,30 @@ typedef enum MIPSIns { | |||
| 298 | MIPSI_CVT_W_D = 0x46200024, | 348 | MIPSI_CVT_W_D = 0x46200024, |
| 299 | MIPSI_CVT_S_W = 0x46800020, | 349 | MIPSI_CVT_S_W = 0x46800020, |
| 300 | MIPSI_CVT_D_W = 0x46800021, | 350 | MIPSI_CVT_D_W = 0x46800021, |
| 351 | MIPSI_CVT_S_L = 0x46a00020, | ||
| 352 | MIPSI_CVT_D_L = 0x46a00021, | ||
| 301 | 353 | ||
| 302 | MIPSI_TRUNC_W_S = 0x4600000d, | 354 | MIPSI_TRUNC_W_S = 0x4600000d, |
| 303 | MIPSI_TRUNC_W_D = 0x4620000d, | 355 | MIPSI_TRUNC_W_D = 0x4620000d, |
| 356 | MIPSI_TRUNC_L_S = 0x46000009, | ||
| 357 | MIPSI_TRUNC_L_D = 0x46200009, | ||
| 304 | MIPSI_FLOOR_W_S = 0x4600000f, | 358 | MIPSI_FLOOR_W_S = 0x4600000f, |
| 305 | MIPSI_FLOOR_W_D = 0x4620000f, | 359 | MIPSI_FLOOR_W_D = 0x4620000f, |
| 306 | 360 | ||
| 307 | MIPSI_MFC1 = 0x44000000, | 361 | MIPSI_MFC1 = 0x44000000, |
| 308 | MIPSI_MTC1 = 0x44800000, | 362 | MIPSI_MTC1 = 0x44800000, |
| 363 | MIPSI_DMTC1 = 0x44a00000, | ||
| 364 | MIPSI_DMFC1 = 0x44200000, | ||
| 309 | 365 | ||
| 310 | MIPSI_BC1F = 0x45000000, | 366 | MIPSI_BC1F = 0x45000000, |
| 311 | MIPSI_BC1T = 0x45010000, | 367 | MIPSI_BC1T = 0x45010000, |
| 312 | 368 | ||
| 313 | MIPSI_C_EQ_D = 0x46200032, | 369 | MIPSI_C_EQ_D = 0x46200032, |
| 370 | MIPSI_C_OLT_S = 0x46000034, | ||
| 314 | MIPSI_C_OLT_D = 0x46200034, | 371 | MIPSI_C_OLT_D = 0x46200034, |
| 315 | MIPSI_C_ULT_D = 0x46200035, | 372 | MIPSI_C_ULT_D = 0x46200035, |
| 316 | MIPSI_C_OLE_D = 0x46200036, | 373 | MIPSI_C_OLE_D = 0x46200036, |
| 317 | MIPSI_C_ULE_D = 0x46200037, | 374 | MIPSI_C_ULE_D = 0x46200037, |
| 318 | |||
| 319 | } MIPSIns; | 375 | } MIPSIns; |
| 320 | 376 | ||
| 321 | #endif | 377 | #endif |
diff --git a/src/lj_trace.c b/src/lj_trace.c index 4cd925ed..80a7f024 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
| @@ -319,13 +319,15 @@ void lj_trace_initstate(global_State *g) | |||
| 319 | /* Initialize 32/64 bit constants. */ | 319 | /* Initialize 32/64 bit constants. */ |
| 320 | #if LJ_TARGET_X86ORX64 | 320 | #if LJ_TARGET_X86ORX64 |
| 321 | J->k64[LJ_K64_TOBIT].u64 = U64x(43380000,00000000); | 321 | J->k64[LJ_K64_TOBIT].u64 = U64x(43380000,00000000); |
| 322 | J->k64[LJ_K64_2P64].u64 = U64x(43f00000,00000000); | ||
| 323 | J->k64[LJ_K64_M2P64].u64 = U64x(c3f00000,00000000); | ||
| 324 | #if LJ_32 | 322 | #if LJ_32 |
| 325 | J->k64[LJ_K64_M2P64_31].u64 = U64x(c1e00000,00000000); | 323 | J->k64[LJ_K64_M2P64_31].u64 = U64x(c1e00000,00000000); |
| 326 | #endif | 324 | #endif |
| 325 | J->k64[LJ_K64_2P64].u64 = U64x(43f00000,00000000); | ||
| 327 | J->k32[LJ_K32_M2P64_31] = LJ_64 ? 0xdf800000 : 0xcf000000; | 326 | J->k32[LJ_K32_M2P64_31] = LJ_64 ? 0xdf800000 : 0xcf000000; |
| 328 | #endif | 327 | #endif |
| 328 | #if LJ_TARGET_X86ORX64 || LJ_TARGET_MIPS64 | ||
| 329 | J->k64[LJ_K64_M2P64].u64 = U64x(c3f00000,00000000); | ||
| 330 | #endif | ||
| 329 | #if LJ_TARGET_PPC | 331 | #if LJ_TARGET_PPC |
| 330 | J->k32[LJ_K32_2P52_2P31] = 0x59800004; | 332 | J->k32[LJ_K32_2P52_2P31] = 0x59800004; |
| 331 | J->k32[LJ_K32_2P52] = 0x59800000; | 333 | J->k32[LJ_K32_2P52] = 0x59800000; |
| @@ -335,6 +337,11 @@ void lj_trace_initstate(global_State *g) | |||
| 335 | #endif | 337 | #endif |
| 336 | #if LJ_TARGET_MIPS | 338 | #if LJ_TARGET_MIPS |
| 337 | J->k64[LJ_K64_2P31].u64 = U64x(41e00000,00000000); | 339 | J->k64[LJ_K64_2P31].u64 = U64x(41e00000,00000000); |
| 340 | #if LJ_64 | ||
| 341 | J->k64[LJ_K64_2P63].u64 = U64x(43e00000,00000000); | ||
| 342 | J->k32[LJ_K32_2P63] = 0x5f000000; | ||
| 343 | J->k32[LJ_K32_M2P64] = 0xdf800000; | ||
| 344 | #endif | ||
| 338 | #endif | 345 | #endif |
| 339 | } | 346 | } |
| 340 | 347 | ||
diff --git a/src/vm_mips64.dasc b/src/vm_mips64.dasc index c518c306..f0c22a74 100644 --- a/src/vm_mips64.dasc +++ b/src/vm_mips64.dasc | |||
| @@ -327,7 +327,13 @@ | |||
| 327 | |.macro jmp_extern; jr CFUNCADDR; .endmacro | 327 | |.macro jmp_extern; jr CFUNCADDR; .endmacro |
| 328 | | | 328 | | |
| 329 | |.macro hotcheck, delta, target | 329 | |.macro hotcheck, delta, target |
| 330 | | NYI | 330 | | dsrl TMP1, PC, 1 |
| 331 | | andi TMP1, TMP1, 126 | ||
| 332 | | daddu TMP1, TMP1, DISPATCH | ||
| 333 | | lhu TMP2, GG_DISP2HOT(TMP1) | ||
| 334 | | addiu TMP2, TMP2, -delta | ||
| 335 | | bltz TMP2, target | ||
| 336 | |. sh TMP2, GG_DISP2HOT(TMP1) | ||
| 331 | |.endmacro | 337 | |.endmacro |
| 332 | | | 338 | | |
| 333 | |.macro hotloop | 339 | |.macro hotloop |
| @@ -2150,7 +2156,21 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2150 | |//----------------------------------------------------------------------- | 2156 | |//----------------------------------------------------------------------- |
| 2151 | | | 2157 | | |
| 2152 | |->vm_record: // Dispatch target for recording phase. | 2158 | |->vm_record: // Dispatch target for recording phase. |
| 2153 | | NYI | 2159 | |.if JIT |
| 2160 | | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) | ||
| 2161 | | andi AT, TMP3, HOOK_VMEVENT // No recording while in vmevent. | ||
| 2162 | | bnez AT, >5 | ||
| 2163 | | // Decrement the hookcount for consistency, but always do the call. | ||
| 2164 | |. lw TMP2, DISPATCH_GL(hookcount)(DISPATCH) | ||
| 2165 | | andi AT, TMP3, HOOK_ACTIVE | ||
| 2166 | | bnez AT, >1 | ||
| 2167 | |. addiu TMP2, TMP2, -1 | ||
| 2168 | | andi AT, TMP3, LUA_MASKLINE|LUA_MASKCOUNT | ||
| 2169 | | beqz AT, >1 | ||
| 2170 | |. nop | ||
| 2171 | | b >1 | ||
| 2172 | |. sw TMP2, DISPATCH_GL(hookcount)(DISPATCH) | ||
| 2173 | |.endif | ||
| 2154 | | | 2174 | | |
| 2155 | |->vm_rethook: // Dispatch target for return hooks. | 2175 | |->vm_rethook: // Dispatch target for return hooks. |
| 2156 | | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) | 2176 | | lbu TMP3, DISPATCH_GL(hookmask)(DISPATCH) |
| @@ -2201,7 +2221,25 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2201 | |. lw MULTRES, -24+LO(RB) // Restore MULTRES for *M ins. | 2221 | |. lw MULTRES, -24+LO(RB) // Restore MULTRES for *M ins. |
| 2202 | | | 2222 | | |
| 2203 | |->vm_hotloop: // Hot loop counter underflow. | 2223 | |->vm_hotloop: // Hot loop counter underflow. |
| 2204 | | NYI | 2224 | |.if JIT |
| 2225 | | ld LFUNC:TMP1, FRAME_FUNC(BASE) | ||
| 2226 | | daddiu CARG1, DISPATCH, GG_DISP2J | ||
| 2227 | | cleartp LFUNC:TMP1 | ||
| 2228 | | sd PC, SAVE_PC | ||
| 2229 | | ld TMP1, LFUNC:TMP1->pc | ||
| 2230 | | move CARG2, PC | ||
| 2231 | | sd L, DISPATCH_J(L)(DISPATCH) | ||
| 2232 | | lbu TMP1, PC2PROTO(framesize)(TMP1) | ||
| 2233 | | load_got lj_trace_hot | ||
| 2234 | | sd BASE, L->base | ||
| 2235 | | dsll TMP1, TMP1, 3 | ||
| 2236 | | daddu TMP1, BASE, TMP1 | ||
| 2237 | | call_intern lj_trace_hot // (jit_State *J, const BCIns *pc) | ||
| 2238 | |. sd TMP1, L->top | ||
| 2239 | | b <3 | ||
| 2240 | |. nop | ||
| 2241 | |.endif | ||
| 2242 | | | ||
| 2205 | | | 2243 | | |
| 2206 | |->vm_callhook: // Dispatch target for call hooks. | 2244 | |->vm_callhook: // Dispatch target for call hooks. |
| 2207 | |.if JIT | 2245 | |.if JIT |
| @@ -2235,21 +2273,69 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2235 | | | 2273 | | |
| 2236 | |->cont_stitch: // Trace stitching. | 2274 | |->cont_stitch: // Trace stitching. |
| 2237 | |.if JIT | 2275 | |.if JIT |
| 2238 | | NYI | 2276 | | // RA = resultptr, RB = meta base |
| 2277 | | lw INS, -4(PC) | ||
| 2278 | | ld TRACE:TMP2, -40(RB) // Save previous trace. | ||
| 2279 | | decode_RA8a RC, INS | ||
| 2280 | | daddiu AT, MULTRES, -8 | ||
| 2281 | | cleartp TRACE:TMP2 | ||
| 2282 | | decode_RA8b RC | ||
| 2283 | | beqz AT, >2 | ||
| 2284 | |. daddu RC, BASE, RC // Call base. | ||
| 2285 | |1: // Move results down. | ||
| 2286 | | ld CARG1, 0(RA) | ||
| 2287 | | daddiu AT, AT, -8 | ||
| 2288 | | daddiu RA, RA, 8 | ||
| 2289 | | sd CARG1, 0(RC) | ||
| 2290 | | bnez AT, <1 | ||
| 2291 | |. daddiu RC, RC, 8 | ||
| 2292 | |2: | ||
| 2293 | | decode_RA8a RA, INS | ||
| 2294 | | decode_RB8a RB, INS | ||
| 2295 | | decode_RA8b RA | ||
| 2296 | | decode_RB8b RB | ||
| 2297 | | daddu RA, RA, RB | ||
| 2298 | | daddu RA, BASE, RA | ||
| 2299 | |3: | ||
| 2300 | | sltu AT, RC, RA | ||
| 2301 | | bnez AT, >9 // More results wanted? | ||
| 2302 | |. nop | ||
| 2303 | | | ||
| 2304 | | lhu TMP3, TRACE:TMP2->traceno | ||
| 2305 | | lhu RD, TRACE:TMP2->link | ||
| 2306 | | beq RD, TMP3, ->cont_nop // Blacklisted. | ||
| 2307 | |. load_got lj_dispatch_stitch | ||
| 2308 | | bnez RD, =>BC_JLOOP // Jump to stitched trace. | ||
| 2309 | |. sll RD, RD, 3 | ||
| 2310 | | | ||
| 2311 | | // Stitch a new trace to the previous trace. | ||
| 2312 | | sw TMP3, DISPATCH_J(exitno)(DISPATCH) | ||
| 2313 | | sd L, DISPATCH_J(L)(DISPATCH) | ||
| 2314 | | sd BASE, L->base | ||
| 2315 | | daddiu CARG1, DISPATCH, GG_DISP2J | ||
| 2316 | | call_intern lj_dispatch_stitch // (jit_State *J, const BCIns *pc) | ||
| 2317 | |. move CARG2, PC | ||
| 2318 | | b ->cont_nop | ||
| 2319 | |. ld BASE, L->base | ||
| 2320 | | | ||
| 2321 | |9: | ||
| 2322 | | sd TISNIL, 0(RC) | ||
| 2323 | | b <3 | ||
| 2324 | |. daddiu RC, RC, 8 | ||
| 2239 | |.endif | 2325 | |.endif |
| 2240 | | | 2326 | | |
| 2241 | |->vm_profhook: // Dispatch target for profiler hook. | 2327 | |->vm_profhook: // Dispatch target for profiler hook. |
| 2242 | #if LJ_HASPROFILE | 2328 | #if LJ_HASPROFILE |
| 2243 | | load_got lj_dispatch_profile | 2329 | | load_got lj_dispatch_profile |
| 2244 | | sw MULTRES, SAVE_MULTRES | 2330 | | sd MULTRES, SAVE_MULTRES |
| 2245 | | move CARG2, PC | 2331 | | move CARG2, PC |
| 2246 | | sw BASE, L->base | 2332 | | sd BASE, L->base |
| 2247 | | call_intern lj_dispatch_profile // (lua_State *L, const BCIns *pc) | 2333 | | call_intern lj_dispatch_profile // (lua_State *L, const BCIns *pc) |
| 2248 | |. move CARG1, L | 2334 | |. move CARG1, L |
| 2249 | | // HOOK_PROFILE is off again, so re-dispatch to dynamic instruction. | 2335 | | // HOOK_PROFILE is off again, so re-dispatch to dynamic instruction. |
| 2250 | | daddiu PC, PC, -4 | 2336 | | daddiu PC, PC, -4 |
| 2251 | | b ->cont_nop | 2337 | | b ->cont_nop |
| 2252 | |. lw BASE, L->base | 2338 | |. ld BASE, L->base |
| 2253 | #endif | 2339 | #endif |
| 2254 | | | 2340 | | |
| 2255 | |//----------------------------------------------------------------------- | 2341 | |//----------------------------------------------------------------------- |
| @@ -2259,6 +2345,7 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2259 | |.macro savex_, a, b | 2345 | |.macro savex_, a, b |
| 2260 | |.if FPU | 2346 | |.if FPU |
| 2261 | | sdc1 f..a, a*8(sp) | 2347 | | sdc1 f..a, a*8(sp) |
| 2348 | | sdc1 f..b, b*8(sp) | ||
| 2262 | | sd r..a, 32*8+a*8(sp) | 2349 | | sd r..a, 32*8+a*8(sp) |
| 2263 | | sd r..b, 32*8+b*8(sp) | 2350 | | sd r..b, 32*8+b*8(sp) |
| 2264 | |.else | 2351 | |.else |
| @@ -2269,11 +2356,124 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2269 | | | 2356 | | |
| 2270 | |->vm_exit_handler: | 2357 | |->vm_exit_handler: |
| 2271 | |.if JIT | 2358 | |.if JIT |
| 2272 | | NYI | 2359 | |.if FPU |
| 2360 | | daddiu sp, sp, -(32*8+32*8) | ||
| 2361 | |.else | ||
| 2362 | | daddiu sp, sp, -(32*8) | ||
| 2363 | |.endif | ||
| 2364 | | savex_ 0, 1 | ||
| 2365 | | savex_ 2, 3 | ||
| 2366 | | savex_ 4, 5 | ||
| 2367 | | savex_ 6, 7 | ||
| 2368 | | savex_ 8, 9 | ||
| 2369 | | savex_ 10, 11 | ||
| 2370 | | savex_ 12, 13 | ||
| 2371 | | savex_ 14, 15 | ||
| 2372 | | savex_ 16, 17 | ||
| 2373 | | savex_ 18, 19 | ||
| 2374 | | savex_ 20, 21 | ||
| 2375 | | savex_ 22, 23 | ||
| 2376 | | savex_ 24, 25 | ||
| 2377 | | savex_ 26, 27 | ||
| 2378 | | savex_ 28, 30 | ||
| 2379 | |.if FPU | ||
| 2380 | | sdc1 f29, 29*8(sp) | ||
| 2381 | | sdc1 f31, 31*8(sp) | ||
| 2382 | | sd r0, 32*8+31*8(sp) // Clear RID_TMP. | ||
| 2383 | | daddiu TMP2, sp, 32*8+32*8 // Recompute original value of sp. | ||
| 2384 | | sd TMP2, 32*8+29*8(sp) // Store sp in RID_SP | ||
| 2385 | |.else | ||
| 2386 | | sd r0, 31*8(sp) // Clear RID_TMP. | ||
| 2387 | | daddiu TMP2, sp, 32*8 // Recompute original value of sp. | ||
| 2388 | | sd TMP2, 29*8(sp) // Store sp in RID_SP | ||
| 2389 | |.endif | ||
| 2390 | | li_vmstate EXIT | ||
| 2391 | | daddiu DISPATCH, JGL, -GG_DISP2G-32768 | ||
| 2392 | | lw TMP1, 0(TMP2) // Load exit number. | ||
| 2393 | | st_vmstate | ||
| 2394 | | ld L, DISPATCH_GL(cur_L)(DISPATCH) | ||
| 2395 | | ld BASE, DISPATCH_GL(jit_base)(DISPATCH) | ||
| 2396 | | load_got lj_trace_exit | ||
| 2397 | | sd L, DISPATCH_J(L)(DISPATCH) | ||
| 2398 | | sw ra, DISPATCH_J(parent)(DISPATCH) // Store trace number. | ||
| 2399 | | sd BASE, L->base | ||
| 2400 | | sw TMP1, DISPATCH_J(exitno)(DISPATCH) // Store exit number. | ||
| 2401 | | daddiu CARG1, DISPATCH, GG_DISP2J | ||
| 2402 | | sd r0, DISPATCH_GL(jit_base)(DISPATCH) | ||
| 2403 | | call_intern lj_trace_exit // (jit_State *J, ExitState *ex) | ||
| 2404 | |. move CARG2, sp | ||
| 2405 | | // Returns MULTRES (unscaled) or negated error code. | ||
| 2406 | | ld TMP1, L->cframe | ||
| 2407 | | li AT, -4 | ||
| 2408 | | ld BASE, L->base | ||
| 2409 | | and sp, TMP1, AT | ||
| 2410 | | ld PC, SAVE_PC // Get SAVE_PC. | ||
| 2411 | | b >1 | ||
| 2412 | |. sd L, SAVE_L // Set SAVE_L (on-trace resume/yield). | ||
| 2273 | |.endif | 2413 | |.endif |
| 2274 | |->vm_exit_interp: | 2414 | |->vm_exit_interp: |
| 2275 | |.if JIT | 2415 | |.if JIT |
| 2276 | | NYI | 2416 | | // CRET1 = MULTRES or negated error code, BASE, PC and JGL set. |
| 2417 | | ld L, SAVE_L | ||
| 2418 | | daddiu DISPATCH, JGL, -GG_DISP2G-32768 | ||
| 2419 | | sd BASE, L->base | ||
| 2420 | |1: | ||
| 2421 | | bltz CRET1, >9 // Check for error from exit. | ||
| 2422 | |. ld LFUNC:RB, FRAME_FUNC(BASE) | ||
| 2423 | | .FPU lui TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float). | ||
| 2424 | | dsll MULTRES, CRET1, 3 | ||
| 2425 | | cleartp LFUNC:RB | ||
| 2426 | | sd MULTRES, SAVE_MULTRES | ||
| 2427 | | li TISNIL, LJ_TNIL | ||
| 2428 | | li TISNUM, LJ_TISNUM // Setup type comparison constants. | ||
| 2429 | | .FPU mtc1 TMP3, TOBIT | ||
| 2430 | | ld TMP1, LFUNC:RB->pc | ||
| 2431 | | sd r0, DISPATCH_GL(jit_base)(DISPATCH) | ||
| 2432 | | ld KBASE, PC2PROTO(k)(TMP1) | ||
| 2433 | | .FPU cvt.d.s TOBIT, TOBIT | ||
| 2434 | | // Modified copy of ins_next which handles function header dispatch, too. | ||
| 2435 | | lw INS, 0(PC) | ||
| 2436 | | daddiu PC, PC, 4 | ||
| 2437 | | // Assumes TISNIL == ~LJ_VMST_INTERP == -1 | ||
| 2438 | | sw TISNIL, DISPATCH_GL(vmstate)(DISPATCH) | ||
| 2439 | | decode_OP8a TMP1, INS | ||
| 2440 | | decode_OP8b TMP1 | ||
| 2441 | | sltiu TMP2, TMP1, BC_FUNCF*8 | ||
| 2442 | | daddu TMP0, DISPATCH, TMP1 | ||
| 2443 | | decode_RD8a RD, INS | ||
| 2444 | | ld AT, 0(TMP0) | ||
| 2445 | | decode_RA8a RA, INS | ||
| 2446 | | beqz TMP2, >2 | ||
| 2447 | |. decode_RA8b RA | ||
| 2448 | | jr AT | ||
| 2449 | |. decode_RD8b RD | ||
| 2450 | |2: | ||
| 2451 | | sltiu TMP2, TMP1, (BC_FUNCC+2)*8 // Fast function? | ||
| 2452 | | bnez TMP2, >3 | ||
| 2453 | |. ld TMP1, FRAME_PC(BASE) | ||
| 2454 | | // Check frame below fast function. | ||
| 2455 | | andi TMP0, TMP1, FRAME_TYPE | ||
| 2456 | | bnez TMP0, >3 // Trace stitching continuation? | ||
| 2457 | |. nop | ||
| 2458 | | // Otherwise set KBASE for Lua function below fast function. | ||
| 2459 | | lw TMP2, -4(TMP1) | ||
| 2460 | | decode_RA8a TMP0, TMP2 | ||
| 2461 | | decode_RA8b TMP0 | ||
| 2462 | | dsubu TMP1, BASE, TMP0 | ||
| 2463 | | ld LFUNC:TMP2, -32(TMP1) | ||
| 2464 | | cleartp LFUNC:TMP2 | ||
| 2465 | | ld TMP1, LFUNC:TMP2->pc | ||
| 2466 | | ld KBASE, PC2PROTO(k)(TMP1) | ||
| 2467 | |3: | ||
| 2468 | | daddiu RC, MULTRES, -8 | ||
| 2469 | | jr AT | ||
| 2470 | |. daddu RA, RA, BASE | ||
| 2471 | | | ||
| 2472 | |9: // Rethrow error from the right C frame. | ||
| 2473 | | load_got lj_err_throw | ||
| 2474 | | negu CARG2, CRET1 | ||
| 2475 | | call_intern lj_err_throw // (lua_State *L, int errcode) | ||
| 2476 | |. move CARG1, L | ||
| 2277 | |.endif | 2477 | |.endif |
| 2278 | | | 2478 | | |
| 2279 | |//----------------------------------------------------------------------- | 2479 | |//----------------------------------------------------------------------- |
| @@ -4013,7 +4213,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
| 4013 | | ins_next2 | 4213 | | ins_next2 |
| 4014 | | | 4214 | | |
| 4015 | |7: // Possible table write barrier for the value. Skip valiswhite check. | 4215 | |7: // Possible table write barrier for the value. Skip valiswhite check. |
| 4016 | | barrierback TAB:RB, TMP3, TMP0, <2 | 4216 | | barrierback TAB:CARG2, TMP3, TMP0, <2 |
| 4017 | break; | 4217 | break; |
| 4018 | 4218 | ||
| 4019 | case BC_TSETM: | 4219 | case BC_TSETM: |
| @@ -4632,7 +4832,18 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
| 4632 | 4832 | ||
| 4633 | case BC_JLOOP: | 4833 | case BC_JLOOP: |
| 4634 | |.if JIT | 4834 | |.if JIT |
| 4635 | | NYI | 4835 | | // RA = base*8 (ignored), RD = traceno*8 |
| 4836 | | ld TMP1, DISPATCH_J(trace)(DISPATCH) | ||
| 4837 | | li AT, 0 | ||
| 4838 | | daddu TMP1, TMP1, RD | ||
| 4839 | | // Traces on MIPS don't store the trace number, so use 0. | ||
| 4840 | | sd AT, DISPATCH_GL(vmstate)(DISPATCH) | ||
| 4841 | | ld TRACE:TMP2, 0(TMP1) | ||
| 4842 | | sd BASE, DISPATCH_GL(jit_base)(DISPATCH) | ||
| 4843 | | ld TMP2, TRACE:TMP2->mcode | ||
| 4844 | | sd L, DISPATCH_GL(tmpbuf.L)(DISPATCH) | ||
| 4845 | | jr TMP2 | ||
| 4846 | |. daddiu JGL, DISPATCH, GG_DISP2G+32768 | ||
| 4636 | |.endif | 4847 | |.endif |
| 4637 | break; | 4848 | break; |
| 4638 | 4849 | ||
| @@ -4694,10 +4905,12 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | |||
| 4694 | 4905 | ||
| 4695 | case BC_IFUNCV: | 4906 | case BC_IFUNCV: |
| 4696 | | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 | 4907 | | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8 |
| 4908 | | li TMP0, LJ_TFUNC | ||
| 4697 | | daddu TMP1, BASE, RC | 4909 | | daddu TMP1, BASE, RC |
| 4698 | | ld TMP2, L->maxstack | 4910 | | ld TMP2, L->maxstack |
| 4911 | | settp LFUNC:RB, TMP0 | ||
| 4699 | | daddu TMP0, RA, RC | 4912 | | daddu TMP0, RA, RC |
| 4700 | | sd LFUNC:RB, 0(TMP1) // Store (untagged) copy of LFUNC. | 4913 | | sd LFUNC:RB, 0(TMP1) // Store (tagged) copy of LFUNC. |
| 4701 | | daddiu TMP3, RC, 16+FRAME_VARG | 4914 | | daddiu TMP3, RC, 16+FRAME_VARG |
| 4702 | | sltu AT, TMP0, TMP2 | 4915 | | sltu AT, TMP0, TMP2 |
| 4703 | | ld KBASE, -4+PC2PROTO(k)(PC) | 4916 | | ld KBASE, -4+PC2PROTO(k)(PC) |
