1197 |
1197 |
1198 return 0; |
1198 return 0; |
1199 } // parse_condition |
1199 } // parse_condition |
1200 |
1200 |
1201 |
1201 |
|
1202 static inline int valid_instruction_char(const char ch) |
|
1203 { |
|
1204 return ( ((ch >= 'A') && (ch <= 'Z')) || |
|
1205 ((ch >= 'a') && (ch <= 'z')) || |
|
1206 ((ch >= '0') && (ch <= '9')) ); |
|
1207 } // valid_instruction_char |
|
1208 |
|
1209 |
1202 static int parse_instruction_token(Context *ctx) |
1210 static int parse_instruction_token(Context *ctx) |
1203 { |
1211 { |
1204 int coissue = 0; |
1212 int coissue = 0; |
1205 int predicated = 0; |
1213 int predicated = 0; |
|
1214 char opstr[32]; |
1206 |
1215 |
1207 if (strcmp(ctx->token, "+") == 0) |
1216 if (strcmp(ctx->token, "+") == 0) |
1208 { |
1217 { |
1209 if (nexttoken(ctx, 0, 1, 0, 0) == FAIL) |
1218 if (nexttoken(ctx, 0, 1, 0, 0) == FAIL) |
1210 return FAIL; |
1219 return FAIL; |
1211 coissue = 1; |
1220 coissue = 1; |
1212 } // if |
1221 } // if |
1213 |
1222 |
|
1223 // All this tapdance is because some instructions mix letters and numbers, |
|
1224 // like "dp4" or "texm3x2depth" and the tokenizer splits words and digits |
|
1225 // into separate tokens, which makes parsing registers ("c31") easier. |
|
1226 opstr[0] = '\0'; |
|
1227 while (1) |
|
1228 { |
|
1229 if ( (strlen(opstr) + strlen(ctx->token)) >= (sizeof (opstr)-1) ) |
|
1230 return fail(ctx, "Expected instruction"); |
|
1231 |
|
1232 char *ptr; |
|
1233 for (ptr = ctx->token; *ptr != '\0'; ptr++) |
|
1234 { |
|
1235 if (!valid_instruction_char(*ptr)) |
|
1236 break; |
|
1237 } // for |
|
1238 |
|
1239 if ((ptr == ctx->token) || (*ptr != '\0')) |
|
1240 { |
|
1241 pushback(ctx); // an invalid char or EOS in this token. |
|
1242 break; |
|
1243 } // if |
|
1244 |
|
1245 strcat(opstr, ctx->token); |
|
1246 |
|
1247 if (nexttoken(ctx, 0, 0, 1, 1) == FAIL) |
|
1248 return FAIL; |
|
1249 } // while |
|
1250 |
1214 int i; |
1251 int i; |
1215 int valid_opcode = 0; |
1252 int valid_opcode = 0; |
1216 const Instruction *instruction = NULL; |
1253 const Instruction *instruction = NULL; |
1217 for (i = 0; i < STATICARRAYLEN(instructions); i++) |
1254 for (i = 0; i < STATICARRAYLEN(instructions); i++) |
1218 { |
1255 { |
1219 instruction = &instructions[i]; |
1256 instruction = &instructions[i]; |
1220 if (instruction->opcode_string == NULL) |
1257 if (instruction->opcode_string == NULL) |
1221 continue; // skip this. |
1258 continue; // skip this. |
1222 else if (strcasecmp(ctx->token, instruction->opcode_string) != 0) |
1259 else if (strcasecmp(opstr, instruction->opcode_string) != 0) |
1223 continue; // not us. |
1260 continue; // not us. |
1224 valid_opcode = 1; |
1261 valid_opcode = 1; |
1225 break; |
1262 break; |
1226 } // for |
1263 } // for |
1227 |
1264 |
1228 uint32 opcode = (uint32) i; |
1265 uint32 opcode = (uint32) i; |
1229 uint32 controls = 0; |
1266 uint32 controls = 0; |
1230 |
1267 |
1231 if (!valid_opcode) |
1268 if (!valid_opcode) |
1232 return failf(ctx, "Unknown instruction '%s'", ctx->token); |
1269 return failf(ctx, "Unknown instruction '%s'", opstr); |
1233 |
1270 |
1234 // This might need to be IFC instead of IF. |
1271 // This might need to be IFC instead of IF. |
1235 if (strcmp(instruction->opcode_string, "IF") == 0) |
1272 if (strcmp(instruction->opcode_string, "IF") == 0) |
1236 { |
1273 { |
1237 if (parse_condition(ctx, &controls)) |
1274 if (parse_condition(ctx, &controls)) |