aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r--src/lj_asm.c209
1 files changed, 159 insertions, 50 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c
index 1304c180..231e76fc 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -949,44 +949,6 @@ static void asm_snap_prep(ASMState *as)
949 949
950/* -- Miscellaneous helpers ----------------------------------------------- */ 950/* -- Miscellaneous helpers ----------------------------------------------- */
951 951
952/* Collect arguments from CALL* and CARG instructions. */
953static void asm_collectargs(ASMState *as, IRIns *ir,
954 const CCallInfo *ci, IRRef *args)
955{
956 uint32_t n = CCI_NARGS(ci);
957 lua_assert(n <= CCI_NARGS_MAX);
958 if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
959 while (n-- > 1) {
960 ir = IR(ir->op1);
961 lua_assert(ir->o == IR_CARG);
962 args[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
963 }
964 args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
965 lua_assert(IR(ir->op1)->o != IR_CARG);
966}
967
968/* Reconstruct CCallInfo flags for CALLX*. */
969static uint32_t asm_callx_flags(ASMState *as, IRIns *ir)
970{
971 uint32_t nargs = 0;
972 if (ir->op1 != REF_NIL) { /* Count number of arguments first. */
973 IRIns *ira = IR(ir->op1);
974 nargs++;
975 while (ira->o == IR_CARG) { nargs++; ira = IR(ira->op1); }
976 }
977#if LJ_HASFFI
978 if (IR(ir->op2)->o == IR_CARG) { /* Copy calling convention info. */
979 CTypeID id = (CTypeID)IR(IR(ir->op2)->op2)->i;
980 CType *ct = ctype_get(ctype_ctsG(J2G(as->J)), id);
981 nargs |= ((ct->info & CTF_VARARG) ? CCI_VARARG : 0);
982#if LJ_TARGET_X86
983 nargs |= (ctype_cconv(ct->info) << CCI_CC_SHIFT);
984#endif
985 }
986#endif
987 return (nargs | (ir->t.irt << CCI_OTSHIFT));
988}
989
990/* Calculate stack adjustment. */ 952/* Calculate stack adjustment. */
991static int32_t asm_stack_adjust(ASMState *as) 953static int32_t asm_stack_adjust(ASMState *as)
992{ 954{
@@ -1071,7 +1033,9 @@ static void asm_gcstep(ASMState *as, IRIns *ir)
1071 as->gcsteps = 0x80000000; /* Prevent implicit GC check further up. */ 1033 as->gcsteps = 0x80000000; /* Prevent implicit GC check further up. */
1072} 1034}
1073 1035
1074/* -- Buffer handling ----------------------------------------------------- */ 1036/* -- Buffer operations --------------------------------------------------- */
1037
1038static void asm_tvptr(ASMState *as, Reg dest, IRRef ref);
1075 1039
1076static void asm_bufhdr(ASMState *as, IRIns *ir) 1040static void asm_bufhdr(ASMState *as, IRIns *ir)
1077{ 1041{
@@ -1091,10 +1055,6 @@ static void asm_bufhdr(ASMState *as, IRIns *ir)
1091 } 1055 }
1092} 1056}
1093 1057
1094#if !LJ_TARGET_X86ORX64
1095static void asm_tvptr(ASMState *as, Reg dest, IRRef ref);
1096#endif
1097
1098static void asm_bufput(ASMState *as, IRIns *ir) 1058static void asm_bufput(ASMState *as, IRIns *ir)
1099{ 1059{
1100 const CCallInfo *ci; 1060 const CCallInfo *ci;
@@ -1115,14 +1075,8 @@ static void asm_bufput(ASMState *as, IRIns *ir)
1115 } 1075 }
1116 asm_setupresult(as, ir, ci); /* SBuf * */ 1076 asm_setupresult(as, ir, ci); /* SBuf * */
1117 asm_gencall(as, ci, args); 1077 asm_gencall(as, ci, args);
1118 if (args[1] == ASMREF_TMP1) { 1078 if (args[1] == ASMREF_TMP1)
1119#if LJ_TARGET_X86ORX64
1120 emit_rmro(as, XO_LEA, ra_releasetmp(as, ASMREF_TMP1)|REX_64,
1121 RID_ESP, ra_spill(as, IR(ir->op2)));
1122#else
1123 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2); 1079 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2);
1124#endif
1125 }
1126} 1080}
1127 1081
1128static void asm_bufstr(ASMState *as, IRIns *ir) 1082static void asm_bufstr(ASMState *as, IRIns *ir)
@@ -1135,6 +1089,161 @@ static void asm_bufstr(ASMState *as, IRIns *ir)
1135 asm_gencall(as, ci, args); 1089 asm_gencall(as, ci, args);
1136} 1090}
1137 1091
1092/* -- Type conversions ---------------------------------------------------- */
1093
1094static void asm_tostr(ASMState *as, IRIns *ir)
1095{
1096 IRRef args[2];
1097 args[0] = ASMREF_L;
1098 as->gcsteps++;
1099 if (irt_isnum(IR(ir->op1)->t) || (LJ_SOFTFP && (ir+1)->o == IR_HIOP)) {
1100 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromnum];
1101 args[1] = ASMREF_TMP1; /* const lua_Number * */
1102 asm_setupresult(as, ir, ci); /* GCstr * */
1103 asm_gencall(as, ci, args);
1104 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1);
1105 } else {
1106 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromint];
1107 args[1] = ir->op1; /* int32_t k */
1108 asm_setupresult(as, ir, ci); /* GCstr * */
1109 asm_gencall(as, ci, args);
1110 }
1111}
1112
1113#if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86
1114static void asm_conv64(ASMState *as, IRIns *ir)
1115{
1116 IRType st = (IRType)((ir-1)->op2 & IRCONV_SRCMASK);
1117 IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
1118 IRCallID id;
1119 IRRef args[2];
1120 lua_assert((ir-1)->o == IR_CONV && ir->o == IR_HIOP);
1121 args[LJ_BE] = (ir-1)->op1;
1122 args[LJ_LE] = ir->op1;
1123 if (st == IRT_NUM || st == IRT_FLOAT) {
1124 id = IRCALL_fp64_d2l + ((st == IRT_FLOAT) ? 2 : 0) + (dt - IRT_I64);
1125 ir--;
1126 } else {
1127 id = IRCALL_fp64_l2d + ((dt == IRT_FLOAT) ? 2 : 0) + (st - IRT_I64);
1128 }
1129 {
1130#if LJ_TARGET_ARM && !LJ_ABI_SOFTFP
1131 CCallInfo cim = lj_ir_callinfo[id], *ci = &cim;
1132 cim.flags |= CCI_VARARG; /* These calls don't use the hard-float ABI! */
1133#else
1134 const CCallInfo *ci = &lj_ir_callinfo[id];
1135#endif
1136 asm_setupresult(as, ir, ci);
1137 asm_gencall(as, ci, args);
1138 }
1139}
1140#endif
1141
1142/* -- Memory references --------------------------------------------------- */
1143
1144static void asm_newref(ASMState *as, IRIns *ir)
1145{
1146 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_newkey];
1147 IRRef args[3];
1148 if (ir->r == RID_SINK)
1149 return;
1150 args[0] = ASMREF_L; /* lua_State *L */
1151 args[1] = ir->op1; /* GCtab *t */
1152 args[2] = ASMREF_TMP1; /* cTValue *key */
1153 asm_setupresult(as, ir, ci); /* TValue * */
1154 asm_gencall(as, ci, args);
1155 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2);
1156}
1157
1158/* -- Calls --------------------------------------------------------------- */
1159
1160/* Collect arguments from CALL* and CARG instructions. */
1161static void asm_collectargs(ASMState *as, IRIns *ir,
1162 const CCallInfo *ci, IRRef *args)
1163{
1164 uint32_t n = CCI_NARGS(ci);
1165 lua_assert(n <= CCI_NARGS_MAX);
1166 if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
1167 while (n-- > 1) {
1168 ir = IR(ir->op1);
1169 lua_assert(ir->o == IR_CARG);
1170 args[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
1171 }
1172 args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
1173 lua_assert(IR(ir->op1)->o != IR_CARG);
1174}
1175
1176/* Reconstruct CCallInfo flags for CALLX*. */
1177static uint32_t asm_callx_flags(ASMState *as, IRIns *ir)
1178{
1179 uint32_t nargs = 0;
1180 if (ir->op1 != REF_NIL) { /* Count number of arguments first. */
1181 IRIns *ira = IR(ir->op1);
1182 nargs++;
1183 while (ira->o == IR_CARG) { nargs++; ira = IR(ira->op1); }
1184 }
1185#if LJ_HASFFI
1186 if (IR(ir->op2)->o == IR_CARG) { /* Copy calling convention info. */
1187 CTypeID id = (CTypeID)IR(IR(ir->op2)->op2)->i;
1188 CType *ct = ctype_get(ctype_ctsG(J2G(as->J)), id);
1189 nargs |= ((ct->info & CTF_VARARG) ? CCI_VARARG : 0);
1190#if LJ_TARGET_X86
1191 nargs |= (ctype_cconv(ct->info) << CCI_CC_SHIFT);
1192#endif
1193 }
1194#endif
1195 return (nargs | (ir->t.irt << CCI_OTSHIFT));
1196}
1197
1198static void asm_callid(ASMState *as, IRIns *ir, IRCallID id)
1199{
1200 const CCallInfo *ci = &lj_ir_callinfo[id];
1201 IRRef args[2];
1202 args[0] = ir->op1;
1203 args[1] = ir->op2;
1204 asm_setupresult(as, ir, ci);
1205 asm_gencall(as, ci, args);
1206}
1207
1208static void asm_call(ASMState *as, IRIns *ir)
1209{
1210 IRRef args[CCI_NARGS_MAX];
1211 const CCallInfo *ci = &lj_ir_callinfo[ir->op2];
1212 asm_collectargs(as, ir, ci, args);
1213 asm_setupresult(as, ir, ci);
1214 asm_gencall(as, ci, args);
1215}
1216
1217#if !LJ_SOFTFP
1218static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref);
1219
1220#if !LJ_TARGET_X86ORX64
1221static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref)
1222{
1223 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_pow];
1224 IRRef args[2];
1225 args[0] = lref;
1226 args[1] = rref;
1227 asm_setupresult(as, ir, ci);
1228 asm_gencall(as, ci, args);
1229}
1230#endif
1231
1232static int asm_fpjoin_pow(ASMState *as, IRIns *ir)
1233{
1234 IRIns *irp = IR(ir->op1);
1235 if (irp == ir-1 && irp->o == IR_MUL && !ra_used(irp)) {
1236 IRIns *irpp = IR(irp->op1);
1237 if (irpp == ir-2 && irpp->o == IR_FPMATH &&
1238 irpp->op2 == IRFPM_LOG2 && !ra_used(irpp)) {
1239 asm_fppow(as, ir, irpp->op1, irp->op2);
1240 return 1;
1241 }
1242 }
1243 return 0;
1244}
1245#endif
1246
1138/* -- PHI and loop handling ----------------------------------------------- */ 1247/* -- PHI and loop handling ----------------------------------------------- */
1139 1248
1140/* Break a PHI cycle by renaming to a free register (evict if needed). */ 1249/* Break a PHI cycle by renaming to a free register (evict if needed). */