Unified · Split
| @@ -1242,7 +1242,78 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 1241 unmodified lines | |||
| 1242 | 1242 | ||
| 1243 | ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) | 1243 | ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) |
| 1244 | { | 1244 | { |
| 1245 | tcc_error("internal error: subst_asm_operand not implemented"); | 1245 | int r, reg, size, val; |
| 1246 | char buf[64]; | ||
| 1247 | |||
| 1248 | r = sv->r; | ||
| 1249 | if ((r & VT_VALMASK) == VT_CONST) { | ||
| 1250 | if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n' && | ||
| 1251 | modifier != 'P') | ||
| 1252 | cstr_ccat(add_str, '#'); | ||
| 1253 | if (r & VT_SYM) { | ||
| 1254 | const char *name = get_tok_str(sv->sym->v, NULL); | ||
| 1255 | if (sv->sym->v >= SYM_FIRST_ANOM) { | ||
| 1256 | /* In case of anonymous symbols ("L.42", used | ||
| 1257 | for static data labels) we can't find them | ||
| 1258 | in the C symbol table when later looking up | ||
| 1259 | this name. So enter them now into the asm label | ||
| 1260 | list when we still know the symbol. */ | ||
| 1261 | get_asm_sym(tok_alloc(name, strlen(name))->tok, sv->sym); | ||
| 1262 | } | ||
| 1263 | if (tcc_state->leading_underscore) | ||
| 1264 | cstr_ccat(add_str, '_'); | ||
| 1265 | cstr_cat(add_str, name, -1); | ||
| 1266 | if ((uint32_t) sv->c.i == 0) | ||
| 1267 | goto no_offset; | ||
| 1268 | cstr_ccat(add_str, '+'); | ||
| 1269 | } | ||
| 1270 | val = sv->c.i; | ||
| 1271 | if (modifier == 'n') | ||
| 1272 | val = -val; | ||
| 1273 | snprintf(buf, sizeof(buf), "%d", (int) sv->c.i); | ||
| 1274 | cstr_cat(add_str, buf, -1); | ||
| 1275 | no_offset:; | ||
| 1276 | } else if ((r & VT_VALMASK) == VT_LOCAL) { | ||
| 1277 | snprintf(buf, sizeof(buf), "[fp,#%d]", (int) sv->c.i); | ||
| 1278 | cstr_cat(add_str, buf, -1); | ||
| 1279 | } else if (r & VT_LVAL) { | ||
| 1280 | reg = r & VT_VALMASK; | ||
| 1281 | if (reg >= VT_CONST) | ||
| 1282 | tcc_internal_error(""); | ||
| 1283 | snprintf(buf, sizeof(buf), "[%s]", | ||
| 1284 | get_tok_str(TOK_ASM_r0 + reg, NULL)); | ||
| 1285 | cstr_cat(add_str, buf, -1); | ||
| 1286 | } else { | ||
| 1287 | /* register case */ | ||
| 1288 | reg = r & VT_VALMASK; | ||
| 1289 | if (reg >= VT_CONST) | ||
| 1290 | tcc_internal_error(""); | ||
| 1291 | |||
| 1292 | /* choose register operand size */ | ||
| 1293 | if ((sv->type.t & VT_BTYPE) == VT_BYTE || | ||
| 1294 | (sv->type.t & VT_BTYPE) == VT_BOOL) | ||
| 1295 | size = 1; | ||
| 1296 | else if ((sv->type.t & VT_BTYPE) == VT_SHORT) | ||
| 1297 | size = 2; | ||
| 1298 | else | ||
| 1299 | size = 4; | ||
| 1300 | |||
| 1301 | if (modifier == 'b') { | ||
| 1302 | size = 1; | ||
| 1303 | } else if (modifier == 'w') { | ||
| 1304 | size = 2; | ||
| 1305 | } else if (modifier == 'k') { | ||
| 1306 | size = 4; | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | switch (size) { | ||
| 1310 | default: | ||
| 1311 | reg = TOK_ASM_r0 + reg; | ||
| 1312 | break; | ||
| 1313 | } | ||
| 1314 | snprintf(buf, sizeof(buf), "%s", get_tok_str(reg, NULL)); | ||
| 1315 | cstr_cat(add_str, buf, -1); | ||
| 1316 | } | ||
| 1246 | } | 1317 | } |
| 1247 | 1318 | ||
| 1248 | /* generate prolog and epilog code for asm statement */ | 1319 | /* generate prolog and epilog code for asm statement */ |