diff options
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r-- | src/lj_asm.c | 209 |
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. */ | ||
953 | static 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*. */ | ||
969 | static 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. */ |
991 | static int32_t asm_stack_adjust(ASMState *as) | 953 | static 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 | |||
1038 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref); | ||
1075 | 1039 | ||
1076 | static void asm_bufhdr(ASMState *as, IRIns *ir) | 1040 | static 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 | ||
1095 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref); | ||
1096 | #endif | ||
1097 | |||
1098 | static void asm_bufput(ASMState *as, IRIns *ir) | 1058 | static 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 | ||
1128 | static void asm_bufstr(ASMState *as, IRIns *ir) | 1082 | static 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 | |||
1094 | static 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 | ||
1114 | static 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 | |||
1144 | static 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. */ | ||
1161 | static 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*. */ | ||
1177 | static 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 | |||
1198 | static 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 | |||
1208 | static 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 | ||
1218 | static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref); | ||
1219 | |||
1220 | #if !LJ_TARGET_X86ORX64 | ||
1221 | static 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 | |||
1232 | static 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). */ |