diff options
author | Mike Pall <mike> | 2010-12-08 02:36:09 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2010-12-08 02:36:09 +0100 |
commit | 3ef6a53cfa95dbe890ec305368a7e446dbd5aedc (patch) | |
tree | 9546c3ba65bc6d9c2bcdd6cb6abfe8554a52322d /src | |
parent | d778680098f630f4c74324f2fad27bb088d29d78 (diff) | |
download | luajit-3ef6a53cfa95dbe890ec305368a7e446dbd5aedc.tar.gz luajit-3ef6a53cfa95dbe890ec305368a7e446dbd5aedc.tar.bz2 luajit-3ef6a53cfa95dbe890ec305368a7e446dbd5aedc.zip |
FFI: Turn cdata indexing into x86/x64 [base+idx*sz+ofs] addressing.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 6231f134..9c72a864 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -1307,12 +1307,44 @@ static void asm_fusexref(ASMState *as, IRRef ref, RegSet allow) | |||
1307 | as->mrm.base = RID_NONE; | 1307 | as->mrm.base = RID_NONE; |
1308 | } else if (ir->o == IR_STRREF) { | 1308 | } else if (ir->o == IR_STRREF) { |
1309 | asm_fusestrref(as, ir, allow); | 1309 | asm_fusestrref(as, ir, allow); |
1310 | } else if (mayfuse(as, ref) && ir->o == IR_ADD && | ||
1311 | asm_isk32(as, ir->op2, &as->mrm.ofs)) { | ||
1312 | /* NYI: gather index and shifts. */ | ||
1313 | as->mrm.base = (uint8_t)ra_alloc1(as, ir->op1, allow); | ||
1314 | } else { | 1310 | } else { |
1315 | as->mrm.ofs = 0; | 1311 | as->mrm.ofs = 0; |
1312 | if (mayfuse(as, ref) && ir->o == IR_ADD && ra_noreg(ir->r)) { | ||
1313 | /* Gather (base+idx*sz)+ofs as emitted by cdata ptr/array indexing. */ | ||
1314 | IRIns *irx; | ||
1315 | IRRef idx; | ||
1316 | Reg r; | ||
1317 | if (asm_isk32(as, ir->op2, &as->mrm.ofs)) { /* Recognize x+ofs. */ | ||
1318 | ref = ir->op1; | ||
1319 | ir = IR(ref); | ||
1320 | if (!(ir->o == IR_ADD && mayfuse(as, ref) && ra_noreg(ir->r))) | ||
1321 | goto noadd; | ||
1322 | } | ||
1323 | as->mrm.scale = XM_SCALE1; | ||
1324 | idx = ir->op1; | ||
1325 | ref = ir->op2; | ||
1326 | irx = IR(idx); | ||
1327 | if (!(irx->o == IR_BSHL || irx->o == IR_ADD)) { /* Try other operand. */ | ||
1328 | idx = ir->op2; | ||
1329 | ref = ir->op1; | ||
1330 | irx = IR(idx); | ||
1331 | } | ||
1332 | if (mayfuse(as, idx) && ra_noreg(irx->r)) { | ||
1333 | if (irx->o == IR_BSHL && irref_isk(irx->op2) && IR(irx->op2)->i <= 3) { | ||
1334 | /* Recognize idx<<b with b = 0-3, corresponding to sz = (1),2,4,8. */ | ||
1335 | idx = irx->op1; | ||
1336 | as->mrm.scale = (uint8_t)(IR(irx->op2)->i << 6); | ||
1337 | } else if (irx->o == IR_ADD && irx->op1 == irx->op2) { | ||
1338 | /* FOLD does idx*2 ==> idx<<1 ==> idx+idx. */ | ||
1339 | idx = irx->op1; | ||
1340 | as->mrm.scale = XM_SCALE2; | ||
1341 | } | ||
1342 | } | ||
1343 | r = ra_alloc1(as, idx, allow); | ||
1344 | rset_clear(allow, r); | ||
1345 | as->mrm.idx = (uint8_t)r; | ||
1346 | } | ||
1347 | noadd: | ||
1316 | as->mrm.base = (uint8_t)ra_alloc1(as, ref, allow); | 1348 | as->mrm.base = (uint8_t)ra_alloc1(as, ref, allow); |
1317 | } | 1349 | } |
1318 | } | 1350 | } |