Unified · Split
| @@ -1242,7 +1242,78 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 1241 unmodified lines | ||
| 1242 | 1242 | |
| 1243 | 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 | 1319 | /* generate prolog and epilog code for asm statement */ |