1214571Sdim/* Assembler interface for targets using CGEN. -*- C -*- 2214571Sdim CGEN: Cpu tools GENerator 3214571Sdim 4214571Sdim THIS FILE IS MACHINE GENERATED WITH CGEN. 5214571Sdim - the resultant file is machine generated, cgen-asm.in isn't 6214571Sdim 7214571Sdim Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005 8214571Sdim Free Software Foundation, Inc. 9214571Sdim 10214571Sdim This file is part of the GNU Binutils and GDB, the GNU debugger. 11214571Sdim 12214571Sdim This program is free software; you can redistribute it and/or modify 13214571Sdim it under the terms of the GNU General Public License as published by 14214571Sdim the Free Software Foundation; either version 2, or (at your option) 15214571Sdim any later version. 16214571Sdim 17214571Sdim This program is distributed in the hope that it will be useful, 18214571Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 19214571Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20214571Sdim GNU General Public License for more details. 21214571Sdim 22214571Sdim You should have received a copy of the GNU General Public License 23214571Sdim along with this program; if not, write to the Free Software Foundation, Inc., 24214571Sdim 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 25214571Sdim 26214571Sdim/* ??? Eventually more and more of this stuff can go to cpu-independent files. 27214571Sdim Keep that in mind. */ 28214571Sdim 29214571Sdim#include "sysdep.h" 30214571Sdim#include <stdio.h> 31214571Sdim#include "ansidecl.h" 32214571Sdim#include "bfd.h" 33214571Sdim#include "symcat.h" 34214571Sdim#include "mep-desc.h" 35214571Sdim#include "mep-opc.h" 36214571Sdim#include "opintl.h" 37214571Sdim#include "xregex.h" 38214571Sdim#include "libiberty.h" 39214571Sdim#include "safe-ctype.h" 40214571Sdim 41214571Sdim#undef min 42214571Sdim#define min(a,b) ((a) < (b) ? (a) : (b)) 43214571Sdim#undef max 44214571Sdim#define max(a,b) ((a) > (b) ? (a) : (b)) 45214571Sdim 46214571Sdimstatic const char * parse_insn_normal 47214571Sdim (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *); 48214571Sdim 49214571Sdim/* -- assembler routines inserted here. */ 50214571Sdim 51214571Sdim/* -- asm.c */ 52214571Sdim 53214571Sdim#define CGEN_VALIDATE_INSN_SUPPORTED 54214571Sdim 55214571Sdim const char * parse_csrn (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 56214571Sdim const char * parse_tpreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 57214571Sdim const char * parse_spreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); 58214571Sdim const char * parse_mep_align (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *); 59214571Sdim const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *); 60214571Sdimstatic const char * parse_signed16 (CGEN_CPU_DESC, const char **, int, long *); 61214571Sdimstatic const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *); 62214571Sdimstatic const char * parse_lo16 (CGEN_CPU_DESC, const char **, int, long *, long); 63214571Sdimstatic const char * parse_unsigned7 (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *); 64214571Sdimstatic const char * parse_zero (CGEN_CPU_DESC, const char **, int, long *); 65214571Sdim 66214571Sdimconst char * 67214571Sdimparse_csrn (CGEN_CPU_DESC cd, const char **strp, 68214571Sdim CGEN_KEYWORD *keyword_table, long *field) 69214571Sdim{ 70214571Sdim const char *err; 71214571Sdim unsigned long value; 72214571Sdim 73214571Sdim err = cgen_parse_keyword (cd, strp, keyword_table, field); 74214571Sdim if (!err) 75214571Sdim return NULL; 76214571Sdim 77214571Sdim err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value); 78214571Sdim if (err) 79214571Sdim return err; 80214571Sdim *field = value; 81214571Sdim return NULL; 82214571Sdim} 83214571Sdim 84214571Sdim/* begin-cop-ip-parse-handlers */ 85214571Sdimstatic const char * 86214571Sdimparse_fmax_cr (CGEN_CPU_DESC cd, 87214571Sdim const char **strp, 88214571Sdim CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 89214571Sdim long *field) 90214571Sdim{ 91214571Sdim return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_fmax, field); 92214571Sdim} 93214571Sdimstatic const char * 94214571Sdimparse_fmax_ccr (CGEN_CPU_DESC cd, 95214571Sdim const char **strp, 96214571Sdim CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 97214571Sdim long *field) 98214571Sdim{ 99214571Sdim return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_fmax, field); 100214571Sdim} 101214571Sdim/* end-cop-ip-parse-handlers */ 102214571Sdim 103214571Sdimconst char * 104214571Sdimparse_tpreg (CGEN_CPU_DESC cd, const char ** strp, 105214571Sdim CGEN_KEYWORD *keyword_table, long *field) 106214571Sdim{ 107214571Sdim const char *err; 108214571Sdim 109214571Sdim err = cgen_parse_keyword (cd, strp, keyword_table, field); 110214571Sdim if (err) 111214571Sdim return err; 112214571Sdim if (*field != 13) 113214571Sdim return _("Only $tp or $13 allowed for this opcode"); 114214571Sdim return NULL; 115214571Sdim} 116214571Sdim 117214571Sdimconst char * 118214571Sdimparse_spreg (CGEN_CPU_DESC cd, const char ** strp, 119214571Sdim CGEN_KEYWORD *keyword_table, long *field) 120214571Sdim{ 121214571Sdim const char *err; 122214571Sdim 123214571Sdim err = cgen_parse_keyword (cd, strp, keyword_table, field); 124214571Sdim if (err) 125214571Sdim return err; 126214571Sdim if (*field != 15) 127214571Sdim return _("Only $sp or $15 allowed for this opcode"); 128214571Sdim return NULL; 129214571Sdim} 130214571Sdim 131214571Sdimconst char * 132214571Sdimparse_mep_align (CGEN_CPU_DESC cd, const char ** strp, 133214571Sdim enum cgen_operand_type type, long *field) 134214571Sdim{ 135214571Sdim long lsbs = 0; 136214571Sdim const char *err; 137214571Sdim 138214571Sdim switch (type) 139214571Sdim { 140214571Sdim case MEP_OPERAND_PCREL8A2: 141214571Sdim case MEP_OPERAND_PCREL12A2: 142214571Sdim case MEP_OPERAND_PCREL17A2: 143214571Sdim case MEP_OPERAND_PCREL24A2: 144214571Sdim case MEP_OPERAND_CDISP8A2: 145214571Sdim case MEP_OPERAND_CDISP8A4: 146214571Sdim case MEP_OPERAND_CDISP8A8: 147214571Sdim err = cgen_parse_signed_integer (cd, strp, type, field); 148214571Sdim break; 149214571Sdim case MEP_OPERAND_PCABS24A2: 150214571Sdim case MEP_OPERAND_UDISP7: 151214571Sdim case MEP_OPERAND_UDISP7A2: 152214571Sdim case MEP_OPERAND_UDISP7A4: 153214571Sdim case MEP_OPERAND_UIMM7A4: 154214571Sdim case MEP_OPERAND_ADDR24A4: 155214571Sdim err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field); 156214571Sdim break; 157214571Sdim default: 158214571Sdim abort(); 159214571Sdim } 160214571Sdim if (err) 161214571Sdim return err; 162214571Sdim switch (type) 163214571Sdim { 164214571Sdim case MEP_OPERAND_UDISP7: 165214571Sdim lsbs = 0; 166214571Sdim break; 167214571Sdim case MEP_OPERAND_PCREL8A2: 168214571Sdim case MEP_OPERAND_PCREL12A2: 169214571Sdim case MEP_OPERAND_PCREL17A2: 170214571Sdim case MEP_OPERAND_PCREL24A2: 171214571Sdim case MEP_OPERAND_PCABS24A2: 172214571Sdim case MEP_OPERAND_UDISP7A2: 173214571Sdim case MEP_OPERAND_CDISP8A2: 174214571Sdim lsbs = *field & 1; 175214571Sdim break; 176214571Sdim case MEP_OPERAND_UDISP7A4: 177214571Sdim case MEP_OPERAND_UIMM7A4: 178214571Sdim case MEP_OPERAND_ADDR24A4: 179214571Sdim case MEP_OPERAND_CDISP8A4: 180214571Sdim lsbs = *field & 3; 181214571Sdim break; 182214571Sdim case MEP_OPERAND_CDISP8A8: 183214571Sdim lsbs = *field & 7; 184214571Sdim break; 185214571Sdim default: 186214571Sdim /* Safe assumption? */ 187214571Sdim abort (); 188214571Sdim } 189214571Sdim if (lsbs) 190214571Sdim return "Value is not aligned enough"; 191214571Sdim return NULL; 192214571Sdim} 193214571Sdim 194214571Sdimconst char * 195214571Sdimparse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp, 196214571Sdim enum cgen_operand_type type, unsigned long *field) 197214571Sdim{ 198214571Sdim return parse_mep_align (cd, strp, type, (long *) field); 199214571Sdim} 200214571Sdim 201214571Sdim 202214571Sdim/* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed 203214571Sdim constants in a signed context. */ 204214571Sdim 205214571Sdimstatic const char * 206214571Sdimparse_signed16 (CGEN_CPU_DESC cd, 207214571Sdim const char **strp, 208214571Sdim int opindex, 209214571Sdim long *valuep) 210214571Sdim{ 211214571Sdim return parse_lo16 (cd, strp, opindex, valuep, 1); 212214571Sdim} 213214571Sdim 214214571Sdimstatic const char * 215214571Sdimparse_lo16 (CGEN_CPU_DESC cd, 216214571Sdim const char **strp, 217214571Sdim int opindex, 218214571Sdim long *valuep, 219214571Sdim long signedp) 220214571Sdim{ 221214571Sdim const char *errmsg; 222214571Sdim enum cgen_parse_operand_result result_type; 223214571Sdim bfd_vma value; 224214571Sdim 225214571Sdim if (strncasecmp (*strp, "%lo(", 4) == 0) 226214571Sdim { 227214571Sdim *strp += 4; 228214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16, 229214571Sdim & result_type, & value); 230214571Sdim if (**strp != ')') 231214571Sdim return _("missing `)'"); 232214571Sdim ++*strp; 233214571Sdim if (errmsg == NULL 234214571Sdim && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 235214571Sdim value &= 0xffff; 236214571Sdim if (signedp) 237214571Sdim *valuep = (long)(short) value; 238214571Sdim else 239214571Sdim *valuep = value; 240214571Sdim return errmsg; 241214571Sdim } 242214571Sdim 243214571Sdim if (strncasecmp (*strp, "%hi(", 4) == 0) 244214571Sdim { 245214571Sdim *strp += 4; 246214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S, 247214571Sdim & result_type, & value); 248214571Sdim if (**strp != ')') 249214571Sdim return _("missing `)'"); 250214571Sdim ++*strp; 251214571Sdim if (errmsg == NULL 252214571Sdim && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 253214571Sdim value = (value + 0x8000) >> 16; 254214571Sdim *valuep = value; 255214571Sdim return errmsg; 256214571Sdim } 257214571Sdim 258214571Sdim if (strncasecmp (*strp, "%uhi(", 5) == 0) 259214571Sdim { 260214571Sdim *strp += 5; 261214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U, 262214571Sdim & result_type, & value); 263214571Sdim if (**strp != ')') 264214571Sdim return _("missing `)'"); 265214571Sdim ++*strp; 266214571Sdim if (errmsg == NULL 267214571Sdim && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 268214571Sdim value = value >> 16; 269214571Sdim *valuep = value; 270214571Sdim return errmsg; 271214571Sdim } 272214571Sdim 273214571Sdim if (strncasecmp (*strp, "%sdaoff(", 8) == 0) 274214571Sdim { 275214571Sdim *strp += 8; 276214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL, 277214571Sdim NULL, & value); 278214571Sdim if (**strp != ')') 279214571Sdim return _("missing `)'"); 280214571Sdim ++*strp; 281214571Sdim *valuep = value; 282214571Sdim return errmsg; 283214571Sdim } 284214571Sdim 285214571Sdim if (strncasecmp (*strp, "%tpoff(", 7) == 0) 286214571Sdim { 287214571Sdim *strp += 7; 288214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL, 289214571Sdim NULL, & value); 290214571Sdim if (**strp != ')') 291214571Sdim return _("missing `)'"); 292214571Sdim ++*strp; 293214571Sdim *valuep = value; 294214571Sdim return errmsg; 295214571Sdim } 296214571Sdim 297214571Sdim if (**strp == '%') 298214571Sdim return _("invalid %function() here"); 299214571Sdim 300214571Sdim return cgen_parse_signed_integer (cd, strp, opindex, valuep); 301214571Sdim} 302214571Sdim 303214571Sdimstatic const char * 304214571Sdimparse_unsigned16 (CGEN_CPU_DESC cd, 305214571Sdim const char **strp, 306214571Sdim int opindex, 307214571Sdim unsigned long *valuep) 308214571Sdim{ 309214571Sdim return parse_lo16 (cd, strp, opindex, (long *) valuep, 0); 310214571Sdim} 311214571Sdim 312214571Sdim/* A special case of parse_signed16 which accepts only the value zero. */ 313214571Sdim 314214571Sdimstatic const char * 315214571Sdimparse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep) 316214571Sdim{ 317214571Sdim const char *errmsg; 318214571Sdim enum cgen_parse_operand_result result_type; 319214571Sdim bfd_vma value; 320214571Sdim 321214571Sdim /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/ 322214571Sdim 323214571Sdim /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'. 324214571Sdim It will fail and cause ry to be listed as an undefined symbol in the 325214571Sdim listing. */ 326214571Sdim if (strncmp (*strp, "($", 2) == 0) 327214571Sdim return "not zero"; /* any string will do -- will never be seen. */ 328214571Sdim 329214571Sdim if (strncasecmp (*strp, "%lo(", 4) == 0) 330214571Sdim { 331214571Sdim *strp += 4; 332214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16, 333214571Sdim &result_type, &value); 334214571Sdim if (**strp != ')') 335214571Sdim return "missing `)'"; 336214571Sdim ++*strp; 337214571Sdim if (errmsg == NULL 338214571Sdim && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 339214571Sdim return "not zero"; /* any string will do -- will never be seen. */ 340214571Sdim *valuep = value; 341214571Sdim return errmsg; 342214571Sdim } 343214571Sdim 344214571Sdim if (strncasecmp (*strp, "%hi(", 4) == 0) 345214571Sdim { 346214571Sdim *strp += 4; 347214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S, 348214571Sdim &result_type, &value); 349214571Sdim if (**strp != ')') 350214571Sdim return "missing `)'"; 351214571Sdim ++*strp; 352214571Sdim if (errmsg == NULL 353214571Sdim && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 354214571Sdim return "not zero"; /* any string will do -- will never be seen. */ 355214571Sdim *valuep = value; 356214571Sdim return errmsg; 357214571Sdim } 358214571Sdim 359214571Sdim if (strncasecmp (*strp, "%uhi(", 5) == 0) 360214571Sdim { 361214571Sdim *strp += 5; 362214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U, 363214571Sdim &result_type, &value); 364214571Sdim if (**strp != ')') 365214571Sdim return "missing `)'"; 366214571Sdim ++*strp; 367214571Sdim if (errmsg == NULL 368214571Sdim && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 369214571Sdim return "not zero"; /* any string will do -- will never be seen. */ 370214571Sdim *valuep = value; 371214571Sdim return errmsg; 372214571Sdim } 373214571Sdim 374214571Sdim if (strncasecmp (*strp, "%sdaoff(", 8) == 0) 375214571Sdim { 376214571Sdim *strp += 8; 377214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL, 378214571Sdim &result_type, &value); 379214571Sdim if (**strp != ')') 380214571Sdim return "missing `)'"; 381214571Sdim ++*strp; 382214571Sdim if (errmsg == NULL 383214571Sdim && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 384214571Sdim return "not zero"; /* any string will do -- will never be seen. */ 385214571Sdim *valuep = value; 386214571Sdim return errmsg; 387214571Sdim } 388214571Sdim 389214571Sdim if (strncasecmp (*strp, "%tpoff(", 7) == 0) 390214571Sdim { 391214571Sdim *strp += 7; 392214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL, 393214571Sdim &result_type, &value); 394214571Sdim if (**strp != ')') 395214571Sdim return "missing `)'"; 396214571Sdim ++*strp; 397214571Sdim if (errmsg == NULL 398214571Sdim && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 399214571Sdim return "not zero"; /* any string will do -- will never be seen. */ 400214571Sdim *valuep = value; 401214571Sdim return errmsg; 402214571Sdim } 403214571Sdim 404214571Sdim if (**strp == '%') 405214571Sdim return "invalid %function() here"; 406214571Sdim 407214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE, 408214571Sdim &result_type, &value); 409214571Sdim if (errmsg == NULL 410214571Sdim && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0)) 411214571Sdim return "not zero"; /* any string will do -- will never be seen. */ 412214571Sdim 413214571Sdim return errmsg; 414214571Sdim} 415214571Sdim 416214571Sdimstatic const char * 417214571Sdimparse_unsigned7 (CGEN_CPU_DESC cd, const char **strp, 418214571Sdim enum cgen_operand_type opindex, unsigned long *valuep) 419214571Sdim{ 420214571Sdim const char *errmsg; 421214571Sdim bfd_vma value; 422214571Sdim 423214571Sdim /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */ 424214571Sdim 425214571Sdim if (strncasecmp (*strp, "%tpoff(", 7) == 0) 426214571Sdim { 427214571Sdim int reloc; 428214571Sdim *strp += 7; 429214571Sdim switch (opindex) 430214571Sdim { 431214571Sdim case MEP_OPERAND_UDISP7: 432214571Sdim reloc = BFD_RELOC_MEP_TPREL7; 433214571Sdim break; 434214571Sdim case MEP_OPERAND_UDISP7A2: 435214571Sdim reloc = BFD_RELOC_MEP_TPREL7A2; 436214571Sdim break; 437214571Sdim case MEP_OPERAND_UDISP7A4: 438214571Sdim reloc = BFD_RELOC_MEP_TPREL7A4; 439214571Sdim break; 440214571Sdim default: 441214571Sdim /* Safe assumption? */ 442214571Sdim abort (); 443214571Sdim } 444214571Sdim errmsg = cgen_parse_address (cd, strp, opindex, reloc, 445214571Sdim NULL, &value); 446214571Sdim if (**strp != ')') 447214571Sdim return "missing `)'"; 448214571Sdim ++*strp; 449214571Sdim *valuep = value; 450214571Sdim return errmsg; 451214571Sdim } 452214571Sdim 453214571Sdim if (**strp == '%') 454214571Sdim return _("invalid %function() here"); 455214571Sdim 456214571Sdim return parse_mep_alignu (cd, strp, opindex, valuep); 457214571Sdim} 458214571Sdim 459214571Sdim/* BEGIN LIGHTWEIGHT MACRO PROCESSOR. */ 460214571Sdim 461214571Sdim#define MAXARGS 9 462214571Sdim 463214571Sdimtypedef struct 464214571Sdim{ 465214571Sdim char *name; 466214571Sdim char *expansion; 467214571Sdim} macro; 468214571Sdim 469214571Sdimtypedef struct 470214571Sdim{ 471214571Sdim const char *start; 472214571Sdim int len; 473214571Sdim} arg; 474214571Sdim 475214571Sdimmacro macros[] = 476214571Sdim{ 477214571Sdim { "sizeof", "(`1.end + (- `1))"}, 478214571Sdim { "startof", "(`1 | 0)" }, 479214571Sdim { "align4", "(`1&(~3))"}, 480214571Sdim/*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" }, */ 481214571Sdim/*{ "lo", "(`1 & 0xffff)" }, */ 482214571Sdim/*{ "sdaoff", "((`1-__sdabase) & 0x7f)"}, */ 483214571Sdim/*{ "tpoff", "((`1-__tpbase) & 0x7f)"}, */ 484214571Sdim { 0,0 } 485214571Sdim}; 486214571Sdim 487214571Sdimstatic char * expand_string (const char *, int); 488214571Sdim 489214571Sdimstatic const char * 490214571Sdimmep_cgen_expand_macros_and_parse_operand 491214571Sdim (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 492214571Sdim 493214571Sdimstatic char * 494214571Sdimstr_append (char *dest, const char *input, int len) 495214571Sdim{ 496214571Sdim char *new_dest; 497214571Sdim int oldlen; 498214571Sdim 499214571Sdim if (len == 0) 500214571Sdim return dest; 501214571Sdim /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */ 502214571Sdim oldlen = (dest ? strlen(dest) : 0); 503214571Sdim new_dest = realloc (dest, oldlen + len + 1); 504214571Sdim memset (new_dest + oldlen, 0, len + 1); 505214571Sdim return strncat (new_dest, input, len); 506214571Sdim} 507214571Sdim 508214571Sdimstatic macro * 509214571Sdimlookup_macro (const char *name) 510214571Sdim{ 511214571Sdim macro *m; 512214571Sdim 513214571Sdim for (m = macros; m->name; ++m) 514214571Sdim if (strncmp (m->name, name, strlen(m->name)) == 0) 515214571Sdim return m; 516214571Sdim 517214571Sdim return 0; 518214571Sdim} 519214571Sdim 520214571Sdimstatic char * 521214571Sdimexpand_macro (arg *args, int narg, macro *mac) 522214571Sdim{ 523214571Sdim char *result = 0, *rescanned_result = 0; 524214571Sdim char *e = mac->expansion; 525214571Sdim char *mark = e; 526214571Sdim int arg = 0; 527214571Sdim 528214571Sdim /* printf("expanding macro %s with %d args\n", mac->name, narg + 1); */ 529214571Sdim while (*e) 530214571Sdim { 531214571Sdim if (*e == '`' && 532214571Sdim (*e+1) && 533214571Sdim ((*(e + 1) - '1') <= MAXARGS) && 534214571Sdim ((*(e + 1) - '1') <= narg)) 535214571Sdim { 536214571Sdim result = str_append (result, mark, e - mark); 537214571Sdim arg = (*(e + 1) - '1'); 538214571Sdim /* printf("replacing `%d with %s\n", arg+1, args[arg].start); */ 539214571Sdim result = str_append (result, args[arg].start, args[arg].len); 540214571Sdim ++e; 541214571Sdim mark = e+1; 542214571Sdim } 543214571Sdim ++e; 544214571Sdim } 545214571Sdim 546214571Sdim if (mark != e) 547214571Sdim result = str_append (result, mark, e - mark); 548214571Sdim 549214571Sdim if (result) 550214571Sdim { 551214571Sdim rescanned_result = expand_string (result, 0); 552214571Sdim free (result); 553214571Sdim return rescanned_result; 554214571Sdim } 555214571Sdim else 556214571Sdim return result; 557214571Sdim} 558214571Sdim 559214571Sdim#define IN_TEXT 0 560214571Sdim#define IN_ARGS 1 561214571Sdim 562214571Sdimstatic char * 563214571Sdimexpand_string (const char *in, int first_only) 564214571Sdim{ 565214571Sdim int num_expansions = 0; 566214571Sdim int depth = 0; 567214571Sdim int narg = -1; 568214571Sdim arg args[MAXARGS]; 569214571Sdim int state = IN_TEXT; 570214571Sdim const char *mark = in; 571214571Sdim macro *macro = 0; 572214571Sdim 573214571Sdim char *expansion = 0; 574214571Sdim char *result = 0; 575214571Sdim 576214571Sdim while (*in) 577214571Sdim { 578214571Sdim switch (state) 579214571Sdim { 580214571Sdim case IN_TEXT: 581214571Sdim if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0)) 582214571Sdim { 583214571Sdim macro = lookup_macro (in + 1); 584214571Sdim if (macro) 585214571Sdim { 586214571Sdim /* printf("entering state %d at '%s'...\n", state, in); */ 587214571Sdim result = str_append (result, mark, in - mark); 588214571Sdim mark = in; 589214571Sdim in += 1 + strlen (macro->name); 590214571Sdim while (*in == ' ') ++in; 591214571Sdim if (*in != '(') 592214571Sdim { 593214571Sdim state = IN_TEXT; 594214571Sdim macro = 0; 595214571Sdim } 596214571Sdim else 597214571Sdim { 598214571Sdim state = IN_ARGS; 599214571Sdim narg = 0; 600214571Sdim args[narg].start = in + 1; 601214571Sdim args[narg].len = 0; 602214571Sdim mark = in + 1; 603214571Sdim } 604214571Sdim } 605214571Sdim } 606214571Sdim break; 607214571Sdim case IN_ARGS: 608214571Sdim if (depth == 0) 609214571Sdim { 610214571Sdim switch (*in) 611214571Sdim { 612214571Sdim case ',': 613214571Sdim narg++; 614214571Sdim args[narg].start = (in + 1); 615214571Sdim args[narg].len = 0; 616214571Sdim break; 617214571Sdim case ')': 618214571Sdim state = IN_TEXT; 619214571Sdim /* printf("entering state %d at '%s'...\n", state, in); */ 620214571Sdim if (macro) 621214571Sdim { 622214571Sdim expansion = 0; 623214571Sdim expansion = expand_macro (args, narg, macro); 624214571Sdim num_expansions++; 625214571Sdim if (expansion) 626214571Sdim { 627214571Sdim result = str_append (result, expansion, strlen (expansion)); 628214571Sdim free (expansion); 629214571Sdim } 630214571Sdim } 631214571Sdim else 632214571Sdim { 633214571Sdim result = str_append (result, mark, in - mark); 634214571Sdim } 635214571Sdim macro = 0; 636214571Sdim mark = in + 1; 637214571Sdim break; 638214571Sdim case '(': 639214571Sdim depth++; 640214571Sdim default: 641214571Sdim args[narg].len++; 642214571Sdim break; 643214571Sdim } 644214571Sdim } 645214571Sdim else 646214571Sdim { 647214571Sdim if (*in == ')') 648214571Sdim depth--; 649214571Sdim if (narg > -1) 650214571Sdim args[narg].len++; 651214571Sdim } 652214571Sdim 653214571Sdim } 654214571Sdim ++in; 655214571Sdim } 656214571Sdim 657214571Sdim if (mark != in) 658214571Sdim result = str_append (result, mark, in - mark); 659214571Sdim 660214571Sdim return result; 661214571Sdim} 662214571Sdim 663214571Sdim#undef IN_ARGS 664214571Sdim#undef IN_TEXT 665214571Sdim#undef MAXARGS 666214571Sdim 667214571Sdim 668214571Sdim/* END LIGHTWEIGHT MACRO PROCESSOR. */ 669214571Sdim 670214571Sdimconst char * mep_cgen_parse_operand 671214571Sdim (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 672214571Sdim 673214571Sdimconst char * 674214571Sdimmep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex, 675214571Sdim const char ** strp_in, CGEN_FIELDS * fields) 676214571Sdim{ 677214571Sdim const char * errmsg = NULL; 678214571Sdim char *str = 0, *hold = 0; 679214571Sdim const char **strp = 0; 680214571Sdim 681214571Sdim /* Set up a new pointer to macro-expanded string. */ 682214571Sdim str = expand_string (*strp_in, 1); 683214571Sdim /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */ 684214571Sdim 685214571Sdim hold = str; 686214571Sdim strp = (const char **)(&str); 687214571Sdim 688214571Sdim errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields); 689214571Sdim 690214571Sdim /* Now work out the advance. */ 691214571Sdim if (strlen (str) == 0) 692214571Sdim *strp_in += strlen (*strp_in); 693214571Sdim 694214571Sdim else 695214571Sdim { 696214571Sdim if (strstr (*strp_in, str)) 697214571Sdim /* A macro-expansion was pulled off the front. */ 698214571Sdim *strp_in = strstr (*strp_in, str); 699214571Sdim else 700214571Sdim /* A non-macro-expansion was pulled off the front. */ 701214571Sdim *strp_in += (str - hold); 702214571Sdim } 703214571Sdim 704214571Sdim if (hold) 705214571Sdim free (hold); 706214571Sdim 707214571Sdim return errmsg; 708214571Sdim} 709214571Sdim 710214571Sdim#define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand); 711214571Sdim 712214571Sdim/* -- dis.c */ 713214571Sdim 714214571Sdimconst char * mep_cgen_parse_operand 715214571Sdim (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *); 716214571Sdim 717214571Sdim/* Main entry point for operand parsing. 718214571Sdim 719214571Sdim This function is basically just a big switch statement. Earlier versions 720214571Sdim used tables to look up the function to use, but 721214571Sdim - if the table contains both assembler and disassembler functions then 722214571Sdim the disassembler contains much of the assembler and vice-versa, 723214571Sdim - there's a lot of inlining possibilities as things grow, 724214571Sdim - using a switch statement avoids the function call overhead. 725214571Sdim 726214571Sdim This function could be moved into `parse_insn_normal', but keeping it 727214571Sdim separate makes clear the interface between `parse_insn_normal' and each of 728214571Sdim the handlers. */ 729214571Sdim 730214571Sdimconst char * 731214571Sdimmep_cgen_parse_operand (CGEN_CPU_DESC cd, 732214571Sdim int opindex, 733214571Sdim const char ** strp, 734214571Sdim CGEN_FIELDS * fields) 735214571Sdim{ 736214571Sdim const char * errmsg = NULL; 737214571Sdim /* Used by scalar operands that still need to be parsed. */ 738214571Sdim long junk ATTRIBUTE_UNUSED; 739214571Sdim 740214571Sdim switch (opindex) 741214571Sdim { 742214571Sdim case MEP_OPERAND_ADDR24A4 : 743214571Sdim errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_ADDR24A4, (unsigned long *) (& fields->f_24u8a4n)); 744214571Sdim break; 745214571Sdim case MEP_OPERAND_CALLNUM : 746214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CALLNUM, (unsigned long *) (& fields->f_callnum)); 747214571Sdim break; 748214571Sdim case MEP_OPERAND_CCCC : 749214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CCCC, (unsigned long *) (& fields->f_rm)); 750214571Sdim break; 751214571Sdim case MEP_OPERAND_CCRN : 752214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr, & fields->f_ccrn); 753214571Sdim break; 754214571Sdim case MEP_OPERAND_CDISP8 : 755214571Sdim errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_CDISP8, (long *) (& fields->f_8s24)); 756214571Sdim break; 757214571Sdim case MEP_OPERAND_CDISP8A2 : 758214571Sdim errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A2, (long *) (& fields->f_8s24a2)); 759214571Sdim break; 760214571Sdim case MEP_OPERAND_CDISP8A4 : 761214571Sdim errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A4, (long *) (& fields->f_8s24a4)); 762214571Sdim break; 763214571Sdim case MEP_OPERAND_CDISP8A8 : 764214571Sdim errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A8, (long *) (& fields->f_8s24a8)); 765214571Sdim break; 766214571Sdim case MEP_OPERAND_CIMM4 : 767214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CIMM4, (unsigned long *) (& fields->f_rn)); 768214571Sdim break; 769214571Sdim case MEP_OPERAND_CIMM5 : 770214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CIMM5, (unsigned long *) (& fields->f_5u24)); 771214571Sdim break; 772214571Sdim case MEP_OPERAND_CODE16 : 773214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CODE16, (unsigned long *) (& fields->f_16u16)); 774214571Sdim break; 775214571Sdim case MEP_OPERAND_CODE24 : 776214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CODE24, (unsigned long *) (& fields->f_24u4n)); 777214571Sdim break; 778214571Sdim case MEP_OPERAND_CP_FLAG : 779214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr, & junk); 780214571Sdim break; 781214571Sdim case MEP_OPERAND_CRN : 782214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr, & fields->f_crn); 783214571Sdim break; 784214571Sdim case MEP_OPERAND_CRN64 : 785214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr64, & fields->f_crn); 786214571Sdim break; 787214571Sdim case MEP_OPERAND_CRNX : 788214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr, & fields->f_crnx); 789214571Sdim break; 790214571Sdim case MEP_OPERAND_CRNX64 : 791214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr64, & fields->f_crnx); 792214571Sdim break; 793214571Sdim case MEP_OPERAND_CSRN : 794214571Sdim errmsg = parse_csrn (cd, strp, & mep_cgen_opval_h_csr, & fields->f_csrn); 795214571Sdim break; 796214571Sdim case MEP_OPERAND_CSRN_IDX : 797214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, (unsigned long *) (& fields->f_csrn)); 798214571Sdim break; 799214571Sdim case MEP_OPERAND_DBG : 800214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 801214571Sdim break; 802214571Sdim case MEP_OPERAND_DEPC : 803214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 804214571Sdim break; 805214571Sdim case MEP_OPERAND_EPC : 806214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 807214571Sdim break; 808214571Sdim case MEP_OPERAND_EXC : 809214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 810214571Sdim break; 811214571Sdim case MEP_OPERAND_FMAX_CCRN : 812214571Sdim errmsg = parse_fmax_ccr (cd, strp, & mep_cgen_opval_h_ccr, & fields->f_fmax_4_4); 813214571Sdim break; 814214571Sdim case MEP_OPERAND_FMAX_FRD : 815214571Sdim errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frd); 816214571Sdim break; 817214571Sdim case MEP_OPERAND_FMAX_FRD_INT : 818214571Sdim errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frd); 819214571Sdim break; 820214571Sdim case MEP_OPERAND_FMAX_FRM : 821214571Sdim errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frm); 822214571Sdim break; 823214571Sdim case MEP_OPERAND_FMAX_FRN : 824214571Sdim errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frn); 825214571Sdim break; 826214571Sdim case MEP_OPERAND_FMAX_FRN_INT : 827214571Sdim errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frn); 828214571Sdim break; 829214571Sdim case MEP_OPERAND_FMAX_RM : 830214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_fmax_rm); 831214571Sdim break; 832214571Sdim case MEP_OPERAND_HI : 833214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 834214571Sdim break; 835214571Sdim case MEP_OPERAND_LO : 836214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 837214571Sdim break; 838214571Sdim case MEP_OPERAND_LP : 839214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 840214571Sdim break; 841214571Sdim case MEP_OPERAND_MB0 : 842214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 843214571Sdim break; 844214571Sdim case MEP_OPERAND_MB1 : 845214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 846214571Sdim break; 847214571Sdim case MEP_OPERAND_ME0 : 848214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 849214571Sdim break; 850214571Sdim case MEP_OPERAND_ME1 : 851214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 852214571Sdim break; 853214571Sdim case MEP_OPERAND_NPC : 854214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 855214571Sdim break; 856214571Sdim case MEP_OPERAND_OPT : 857214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 858214571Sdim break; 859214571Sdim case MEP_OPERAND_PCABS24A2 : 860214571Sdim errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_PCABS24A2, (unsigned long *) (& fields->f_24u5a2n)); 861214571Sdim break; 862214571Sdim case MEP_OPERAND_PCREL12A2 : 863214571Sdim errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL12A2, (long *) (& fields->f_12s4a2)); 864214571Sdim break; 865214571Sdim case MEP_OPERAND_PCREL17A2 : 866214571Sdim errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL17A2, (long *) (& fields->f_17s16a2)); 867214571Sdim break; 868214571Sdim case MEP_OPERAND_PCREL24A2 : 869214571Sdim errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL24A2, (long *) (& fields->f_24s5a2n)); 870214571Sdim break; 871214571Sdim case MEP_OPERAND_PCREL8A2 : 872214571Sdim errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL8A2, (long *) (& fields->f_8s8a2)); 873214571Sdim break; 874214571Sdim case MEP_OPERAND_PSW : 875214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 876214571Sdim break; 877214571Sdim case MEP_OPERAND_R0 : 878214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk); 879214571Sdim break; 880214571Sdim case MEP_OPERAND_R1 : 881214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk); 882214571Sdim break; 883214571Sdim case MEP_OPERAND_RL : 884214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rl); 885214571Sdim break; 886214571Sdim case MEP_OPERAND_RM : 887214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rm); 888214571Sdim break; 889214571Sdim case MEP_OPERAND_RMA : 890214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rm); 891214571Sdim break; 892214571Sdim case MEP_OPERAND_RN : 893214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn); 894214571Sdim break; 895214571Sdim case MEP_OPERAND_RN3 : 896214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3); 897214571Sdim break; 898214571Sdim case MEP_OPERAND_RN3C : 899214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3); 900214571Sdim break; 901214571Sdim case MEP_OPERAND_RN3L : 902214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3); 903214571Sdim break; 904214571Sdim case MEP_OPERAND_RN3S : 905214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3); 906214571Sdim break; 907214571Sdim case MEP_OPERAND_RN3UC : 908214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3); 909214571Sdim break; 910214571Sdim case MEP_OPERAND_RN3UL : 911214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3); 912214571Sdim break; 913214571Sdim case MEP_OPERAND_RN3US : 914214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3); 915214571Sdim break; 916214571Sdim case MEP_OPERAND_RNC : 917214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn); 918214571Sdim break; 919214571Sdim case MEP_OPERAND_RNL : 920214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn); 921214571Sdim break; 922214571Sdim case MEP_OPERAND_RNS : 923214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn); 924214571Sdim break; 925214571Sdim case MEP_OPERAND_RNUC : 926214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn); 927214571Sdim break; 928214571Sdim case MEP_OPERAND_RNUL : 929214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn); 930214571Sdim break; 931214571Sdim case MEP_OPERAND_RNUS : 932214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn); 933214571Sdim break; 934214571Sdim case MEP_OPERAND_SAR : 935214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk); 936214571Sdim break; 937214571Sdim case MEP_OPERAND_SDISP16 : 938214571Sdim errmsg = parse_signed16 (cd, strp, MEP_OPERAND_SDISP16, (long *) (& fields->f_16s16)); 939214571Sdim break; 940214571Sdim case MEP_OPERAND_SIMM16 : 941214571Sdim errmsg = parse_signed16 (cd, strp, MEP_OPERAND_SIMM16, (long *) (& fields->f_16s16)); 942214571Sdim break; 943214571Sdim case MEP_OPERAND_SIMM6 : 944214571Sdim errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_SIMM6, (long *) (& fields->f_6s8)); 945214571Sdim break; 946214571Sdim case MEP_OPERAND_SIMM8 : 947214571Sdim errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_SIMM8, (long *) (& fields->f_8s8)); 948214571Sdim break; 949214571Sdim case MEP_OPERAND_SP : 950214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk); 951214571Sdim break; 952214571Sdim case MEP_OPERAND_SPR : 953214571Sdim errmsg = parse_spreg (cd, strp, & mep_cgen_opval_h_gpr, & junk); 954214571Sdim break; 955214571Sdim case MEP_OPERAND_TP : 956214571Sdim errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk); 957214571Sdim break; 958214571Sdim case MEP_OPERAND_TPR : 959214571Sdim errmsg = parse_tpreg (cd, strp, & mep_cgen_opval_h_gpr, & junk); 960214571Sdim break; 961214571Sdim case MEP_OPERAND_UDISP2 : 962214571Sdim errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_UDISP2, (long *) (& fields->f_2u6)); 963214571Sdim break; 964214571Sdim case MEP_OPERAND_UDISP7 : 965214571Sdim errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7, (unsigned long *) (& fields->f_7u9)); 966214571Sdim break; 967214571Sdim case MEP_OPERAND_UDISP7A2 : 968214571Sdim errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7A2, (unsigned long *) (& fields->f_7u9a2)); 969214571Sdim break; 970214571Sdim case MEP_OPERAND_UDISP7A4 : 971214571Sdim errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7A4, (unsigned long *) (& fields->f_7u9a4)); 972214571Sdim break; 973214571Sdim case MEP_OPERAND_UIMM16 : 974214571Sdim errmsg = parse_unsigned16 (cd, strp, MEP_OPERAND_UIMM16, (unsigned long *) (& fields->f_16u16)); 975214571Sdim break; 976214571Sdim case MEP_OPERAND_UIMM2 : 977214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM2, (unsigned long *) (& fields->f_2u10)); 978214571Sdim break; 979214571Sdim case MEP_OPERAND_UIMM24 : 980214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM24, (unsigned long *) (& fields->f_24u8n)); 981214571Sdim break; 982214571Sdim case MEP_OPERAND_UIMM3 : 983214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM3, (unsigned long *) (& fields->f_3u5)); 984214571Sdim break; 985214571Sdim case MEP_OPERAND_UIMM4 : 986214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM4, (unsigned long *) (& fields->f_4u8)); 987214571Sdim break; 988214571Sdim case MEP_OPERAND_UIMM5 : 989214571Sdim errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM5, (unsigned long *) (& fields->f_5u8)); 990214571Sdim break; 991214571Sdim case MEP_OPERAND_UIMM7A4 : 992214571Sdim errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_UIMM7A4, (unsigned long *) (& fields->f_7u9a4)); 993214571Sdim break; 994214571Sdim case MEP_OPERAND_ZERO : 995214571Sdim errmsg = parse_zero (cd, strp, MEP_OPERAND_ZERO, (long *) (& junk)); 996214571Sdim break; 997214571Sdim 998214571Sdim default : 999214571Sdim /* xgettext:c-format */ 1000214571Sdim fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex); 1001214571Sdim abort (); 1002214571Sdim } 1003214571Sdim 1004214571Sdim return errmsg; 1005214571Sdim} 1006214571Sdim 1007214571Sdimcgen_parse_fn * const mep_cgen_parse_handlers[] = 1008214571Sdim{ 1009214571Sdim parse_insn_normal, 1010214571Sdim}; 1011214571Sdim 1012214571Sdimvoid 1013214571Sdimmep_cgen_init_asm (CGEN_CPU_DESC cd) 1014214571Sdim{ 1015214571Sdim mep_cgen_init_opcode_table (cd); 1016214571Sdim mep_cgen_init_ibld_table (cd); 1017214571Sdim cd->parse_handlers = & mep_cgen_parse_handlers[0]; 1018214571Sdim cd->parse_operand = mep_cgen_parse_operand; 1019214571Sdim#ifdef CGEN_ASM_INIT_HOOK 1020214571SdimCGEN_ASM_INIT_HOOK 1021214571Sdim#endif 1022214571Sdim} 1023214571Sdim 1024214571Sdim 1025214571Sdim 1026214571Sdim/* Regex construction routine. 1027214571Sdim 1028214571Sdim This translates an opcode syntax string into a regex string, 1029214571Sdim by replacing any non-character syntax element (such as an 1030214571Sdim opcode) with the pattern '.*' 1031214571Sdim 1032214571Sdim It then compiles the regex and stores it in the opcode, for 1033214571Sdim later use by mep_cgen_assemble_insn 1034214571Sdim 1035214571Sdim Returns NULL for success, an error message for failure. */ 1036214571Sdim 1037214571Sdimchar * 1038214571Sdimmep_cgen_build_insn_regex (CGEN_INSN *insn) 1039214571Sdim{ 1040214571Sdim CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn); 1041214571Sdim const char *mnem = CGEN_INSN_MNEMONIC (insn); 1042214571Sdim char rxbuf[CGEN_MAX_RX_ELEMENTS]; 1043214571Sdim char *rx = rxbuf; 1044214571Sdim const CGEN_SYNTAX_CHAR_TYPE *syn; 1045214571Sdim int reg_err; 1046214571Sdim 1047214571Sdim syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); 1048214571Sdim 1049214571Sdim /* Mnemonics come first in the syntax string. */ 1050214571Sdim if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 1051214571Sdim return _("missing mnemonic in syntax string"); 1052214571Sdim ++syn; 1053214571Sdim 1054214571Sdim /* Generate a case sensitive regular expression that emulates case 1055214571Sdim insensitive matching in the "C" locale. We cannot generate a case 1056214571Sdim insensitive regular expression because in Turkish locales, 'i' and 'I' 1057214571Sdim are not equal modulo case conversion. */ 1058214571Sdim 1059214571Sdim /* Copy the literal mnemonic out of the insn. */ 1060214571Sdim for (; *mnem; mnem++) 1061214571Sdim { 1062214571Sdim char c = *mnem; 1063214571Sdim 1064214571Sdim if (ISALPHA (c)) 1065214571Sdim { 1066214571Sdim *rx++ = '['; 1067214571Sdim *rx++ = TOLOWER (c); 1068214571Sdim *rx++ = TOUPPER (c); 1069214571Sdim *rx++ = ']'; 1070214571Sdim } 1071214571Sdim else 1072214571Sdim *rx++ = c; 1073214571Sdim } 1074214571Sdim 1075214571Sdim /* Copy any remaining literals from the syntax string into the rx. */ 1076214571Sdim for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn) 1077214571Sdim { 1078214571Sdim if (CGEN_SYNTAX_CHAR_P (* syn)) 1079214571Sdim { 1080214571Sdim char c = CGEN_SYNTAX_CHAR (* syn); 1081214571Sdim 1082214571Sdim switch (c) 1083214571Sdim { 1084214571Sdim /* Escape any regex metacharacters in the syntax. */ 1085214571Sdim case '.': case '[': case '\\': 1086214571Sdim case '*': case '^': case '$': 1087214571Sdim 1088214571Sdim#ifdef CGEN_ESCAPE_EXTENDED_REGEX 1089214571Sdim case '?': case '{': case '}': 1090214571Sdim case '(': case ')': case '*': 1091214571Sdim case '|': case '+': case ']': 1092214571Sdim#endif 1093214571Sdim *rx++ = '\\'; 1094214571Sdim *rx++ = c; 1095214571Sdim break; 1096214571Sdim 1097214571Sdim default: 1098214571Sdim if (ISALPHA (c)) 1099214571Sdim { 1100214571Sdim *rx++ = '['; 1101214571Sdim *rx++ = TOLOWER (c); 1102214571Sdim *rx++ = TOUPPER (c); 1103214571Sdim *rx++ = ']'; 1104214571Sdim } 1105214571Sdim else 1106214571Sdim *rx++ = c; 1107214571Sdim break; 1108214571Sdim } 1109214571Sdim } 1110214571Sdim else 1111214571Sdim { 1112214571Sdim /* Replace non-syntax fields with globs. */ 1113214571Sdim *rx++ = '.'; 1114214571Sdim *rx++ = '*'; 1115214571Sdim } 1116214571Sdim } 1117214571Sdim 1118214571Sdim /* Trailing whitespace ok. */ 1119214571Sdim * rx++ = '['; 1120214571Sdim * rx++ = ' '; 1121214571Sdim * rx++ = '\t'; 1122214571Sdim * rx++ = ']'; 1123214571Sdim * rx++ = '*'; 1124214571Sdim 1125214571Sdim /* But anchor it after that. */ 1126214571Sdim * rx++ = '$'; 1127214571Sdim * rx = '\0'; 1128214571Sdim 1129214571Sdim CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); 1130214571Sdim reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB); 1131214571Sdim 1132214571Sdim if (reg_err == 0) 1133214571Sdim return NULL; 1134214571Sdim else 1135214571Sdim { 1136214571Sdim static char msg[80]; 1137214571Sdim 1138214571Sdim regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); 1139214571Sdim regfree ((regex_t *) CGEN_INSN_RX (insn)); 1140214571Sdim free (CGEN_INSN_RX (insn)); 1141214571Sdim (CGEN_INSN_RX (insn)) = NULL; 1142214571Sdim return msg; 1143214571Sdim } 1144214571Sdim} 1145214571Sdim 1146214571Sdim 1147214571Sdim/* Default insn parser. 1148214571Sdim 1149214571Sdim The syntax string is scanned and operands are parsed and stored in FIELDS. 1150214571Sdim Relocs are queued as we go via other callbacks. 1151214571Sdim 1152214571Sdim ??? Note that this is currently an all-or-nothing parser. If we fail to 1153214571Sdim parse the instruction, we return 0 and the caller will start over from 1154214571Sdim the beginning. Backtracking will be necessary in parsing subexpressions, 1155214571Sdim but that can be handled there. Not handling backtracking here may get 1156214571Sdim expensive in the case of the m68k. Deal with later. 1157214571Sdim 1158214571Sdim Returns NULL for success, an error message for failure. */ 1159214571Sdim 1160214571Sdimstatic const char * 1161214571Sdimparse_insn_normal (CGEN_CPU_DESC cd, 1162214571Sdim const CGEN_INSN *insn, 1163214571Sdim const char **strp, 1164214571Sdim CGEN_FIELDS *fields) 1165214571Sdim{ 1166214571Sdim /* ??? Runtime added insns not handled yet. */ 1167214571Sdim const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 1168214571Sdim const char *str = *strp; 1169214571Sdim const char *errmsg; 1170214571Sdim const char *p; 1171214571Sdim const CGEN_SYNTAX_CHAR_TYPE * syn; 1172214571Sdim#ifdef CGEN_MNEMONIC_OPERANDS 1173214571Sdim /* FIXME: wip */ 1174214571Sdim int past_opcode_p; 1175214571Sdim#endif 1176214571Sdim 1177214571Sdim /* For now we assume the mnemonic is first (there are no leading operands). 1178214571Sdim We can parse it without needing to set up operand parsing. 1179214571Sdim GAS's input scrubber will ensure mnemonics are lowercase, but we may 1180214571Sdim not be called from GAS. */ 1181214571Sdim p = CGEN_INSN_MNEMONIC (insn); 1182214571Sdim while (*p && TOLOWER (*p) == TOLOWER (*str)) 1183214571Sdim ++p, ++str; 1184214571Sdim 1185214571Sdim if (* p) 1186214571Sdim return _("unrecognized instruction"); 1187214571Sdim 1188214571Sdim#ifndef CGEN_MNEMONIC_OPERANDS 1189214571Sdim if (* str && ! ISSPACE (* str)) 1190214571Sdim return _("unrecognized instruction"); 1191214571Sdim#endif 1192214571Sdim 1193214571Sdim CGEN_INIT_PARSE (cd); 1194214571Sdim cgen_init_parse_operand (cd); 1195214571Sdim#ifdef CGEN_MNEMONIC_OPERANDS 1196214571Sdim past_opcode_p = 0; 1197214571Sdim#endif 1198214571Sdim 1199214571Sdim /* We don't check for (*str != '\0') here because we want to parse 1200214571Sdim any trailing fake arguments in the syntax string. */ 1201214571Sdim syn = CGEN_SYNTAX_STRING (syntax); 1202214571Sdim 1203214571Sdim /* Mnemonics come first for now, ensure valid string. */ 1204214571Sdim if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) 1205214571Sdim abort (); 1206214571Sdim 1207214571Sdim ++syn; 1208214571Sdim 1209214571Sdim while (* syn != 0) 1210214571Sdim { 1211214571Sdim /* Non operand chars must match exactly. */ 1212214571Sdim if (CGEN_SYNTAX_CHAR_P (* syn)) 1213214571Sdim { 1214214571Sdim /* FIXME: While we allow for non-GAS callers above, we assume the 1215214571Sdim first char after the mnemonic part is a space. */ 1216214571Sdim /* FIXME: We also take inappropriate advantage of the fact that 1217214571Sdim GAS's input scrubber will remove extraneous blanks. */ 1218214571Sdim if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn))) 1219214571Sdim { 1220214571Sdim#ifdef CGEN_MNEMONIC_OPERANDS 1221214571Sdim if (CGEN_SYNTAX_CHAR(* syn) == ' ') 1222214571Sdim past_opcode_p = 1; 1223214571Sdim#endif 1224214571Sdim ++ syn; 1225214571Sdim ++ str; 1226214571Sdim } 1227214571Sdim else if (*str) 1228214571Sdim { 1229214571Sdim /* Syntax char didn't match. Can't be this insn. */ 1230214571Sdim static char msg [80]; 1231214571Sdim 1232214571Sdim /* xgettext:c-format */ 1233214571Sdim sprintf (msg, _("syntax error (expected char `%c', found `%c')"), 1234214571Sdim CGEN_SYNTAX_CHAR(*syn), *str); 1235214571Sdim return msg; 1236214571Sdim } 1237214571Sdim else 1238214571Sdim { 1239214571Sdim /* Ran out of input. */ 1240214571Sdim static char msg [80]; 1241214571Sdim 1242214571Sdim /* xgettext:c-format */ 1243214571Sdim sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"), 1244214571Sdim CGEN_SYNTAX_CHAR(*syn)); 1245214571Sdim return msg; 1246214571Sdim } 1247214571Sdim continue; 1248214571Sdim } 1249214571Sdim 1250214571Sdim /* We have an operand of some sort. */ 1251214571Sdim errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), 1252214571Sdim &str, fields); 1253214571Sdim if (errmsg) 1254214571Sdim return errmsg; 1255214571Sdim 1256214571Sdim /* Done with this operand, continue with next one. */ 1257214571Sdim ++ syn; 1258214571Sdim } 1259214571Sdim 1260214571Sdim /* If we're at the end of the syntax string, we're done. */ 1261214571Sdim if (* syn == 0) 1262214571Sdim { 1263214571Sdim /* FIXME: For the moment we assume a valid `str' can only contain 1264214571Sdim blanks now. IE: We needn't try again with a longer version of 1265214571Sdim the insn and it is assumed that longer versions of insns appear 1266214571Sdim before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ 1267214571Sdim while (ISSPACE (* str)) 1268214571Sdim ++ str; 1269214571Sdim 1270214571Sdim if (* str != '\0') 1271214571Sdim return _("junk at end of line"); /* FIXME: would like to include `str' */ 1272214571Sdim 1273214571Sdim return NULL; 1274214571Sdim } 1275214571Sdim 1276214571Sdim /* We couldn't parse it. */ 1277214571Sdim return _("unrecognized instruction"); 1278214571Sdim} 1279214571Sdim 1280214571Sdim/* Main entry point. 1281214571Sdim This routine is called for each instruction to be assembled. 1282214571Sdim STR points to the insn to be assembled. 1283214571Sdim We assume all necessary tables have been initialized. 1284214571Sdim The assembled instruction, less any fixups, is stored in BUF. 1285214571Sdim Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value 1286214571Sdim still needs to be converted to target byte order, otherwise BUF is an array 1287214571Sdim of bytes in target byte order. 1288214571Sdim The result is a pointer to the insn's entry in the opcode table, 1289214571Sdim or NULL if an error occured (an error message will have already been 1290214571Sdim printed). 1291214571Sdim 1292214571Sdim Note that when processing (non-alias) macro-insns, 1293214571Sdim this function recurses. 1294214571Sdim 1295214571Sdim ??? It's possible to make this cpu-independent. 1296214571Sdim One would have to deal with a few minor things. 1297214571Sdim At this point in time doing so would be more of a curiosity than useful 1298214571Sdim [for example this file isn't _that_ big], but keeping the possibility in 1299214571Sdim mind helps keep the design clean. */ 1300214571Sdim 1301214571Sdimconst CGEN_INSN * 1302214571Sdimmep_cgen_assemble_insn (CGEN_CPU_DESC cd, 1303214571Sdim const char *str, 1304214571Sdim CGEN_FIELDS *fields, 1305214571Sdim CGEN_INSN_BYTES_PTR buf, 1306214571Sdim char **errmsg) 1307214571Sdim{ 1308214571Sdim const char *start; 1309214571Sdim CGEN_INSN_LIST *ilist; 1310214571Sdim const char *parse_errmsg = NULL; 1311214571Sdim const char *insert_errmsg = NULL; 1312214571Sdim int recognized_mnemonic = 0; 1313214571Sdim 1314214571Sdim /* Skip leading white space. */ 1315214571Sdim while (ISSPACE (* str)) 1316214571Sdim ++ str; 1317214571Sdim 1318214571Sdim /* The instructions are stored in hashed lists. 1319214571Sdim Get the first in the list. */ 1320214571Sdim ilist = CGEN_ASM_LOOKUP_INSN (cd, str); 1321214571Sdim 1322214571Sdim /* Keep looking until we find a match. */ 1323214571Sdim start = str; 1324214571Sdim for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) 1325214571Sdim { 1326214571Sdim const CGEN_INSN *insn = ilist->insn; 1327214571Sdim recognized_mnemonic = 1; 1328214571Sdim 1329214571Sdim#ifdef CGEN_VALIDATE_INSN_SUPPORTED 1330214571Sdim /* Not usually needed as unsupported opcodes 1331214571Sdim shouldn't be in the hash lists. */ 1332214571Sdim /* Is this insn supported by the selected cpu? */ 1333214571Sdim if (! mep_cgen_insn_supported (cd, insn)) 1334214571Sdim continue; 1335214571Sdim#endif 1336214571Sdim /* If the RELAXED attribute is set, this is an insn that shouldn't be 1337214571Sdim chosen immediately. Instead, it is used during assembler/linker 1338214571Sdim relaxation if possible. */ 1339214571Sdim if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0) 1340214571Sdim continue; 1341214571Sdim 1342214571Sdim str = start; 1343214571Sdim 1344214571Sdim /* Skip this insn if str doesn't look right lexically. */ 1345214571Sdim if (CGEN_INSN_RX (insn) != NULL && 1346214571Sdim regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) 1347214571Sdim continue; 1348214571Sdim 1349214571Sdim /* Allow parse/insert handlers to obtain length of insn. */ 1350214571Sdim CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 1351214571Sdim 1352214571Sdim parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields); 1353214571Sdim if (parse_errmsg != NULL) 1354214571Sdim continue; 1355214571Sdim 1356214571Sdim /* ??? 0 is passed for `pc'. */ 1357214571Sdim insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf, 1358214571Sdim (bfd_vma) 0); 1359214571Sdim if (insert_errmsg != NULL) 1360214571Sdim continue; 1361214571Sdim 1362214571Sdim /* It is up to the caller to actually output the insn and any 1363214571Sdim queued relocs. */ 1364214571Sdim return insn; 1365214571Sdim } 1366214571Sdim 1367214571Sdim { 1368214571Sdim static char errbuf[150]; 1369214571Sdim#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS 1370214571Sdim const char *tmp_errmsg; 1371214571Sdim 1372214571Sdim /* If requesting verbose error messages, use insert_errmsg. 1373214571Sdim Failing that, use parse_errmsg. */ 1374214571Sdim tmp_errmsg = (insert_errmsg ? insert_errmsg : 1375214571Sdim parse_errmsg ? parse_errmsg : 1376214571Sdim recognized_mnemonic ? 1377214571Sdim _("unrecognized form of instruction") : 1378214571Sdim _("unrecognized instruction")); 1379214571Sdim 1380214571Sdim if (strlen (start) > 50) 1381214571Sdim /* xgettext:c-format */ 1382214571Sdim sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start); 1383214571Sdim else 1384214571Sdim /* xgettext:c-format */ 1385214571Sdim sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start); 1386214571Sdim#else 1387214571Sdim if (strlen (start) > 50) 1388214571Sdim /* xgettext:c-format */ 1389214571Sdim sprintf (errbuf, _("bad instruction `%.50s...'"), start); 1390214571Sdim else 1391214571Sdim /* xgettext:c-format */ 1392214571Sdim sprintf (errbuf, _("bad instruction `%.50s'"), start); 1393214571Sdim#endif 1394214571Sdim 1395214571Sdim *errmsg = errbuf; 1396214571Sdim return NULL; 1397214571Sdim } 1398214571Sdim} 1399