tc-tahoe.c revision 1.2
1165138Syongari/* tc-tahoe.c 2165138Syongari Not part of GAS yet. */ 3165138Syongari 4165138Syongari#include "as.h" 5165138Syongari#include "obstack.h" 6165138Syongari 7165138Syongari/* this bit glommed from tahoe-inst.h */ 8165138Syongari 9165138Syongaritypedef unsigned char byte; 10165138Syongaritypedef byte tahoe_opcodeT; 11165138Syongari 12165138Syongari/* 13165138Syongari * This is part of tahoe-ins-parse.c & friends. 14165138Syongari * We want to parse a tahoe instruction text into a tree defined here. 15165138Syongari */ 16165138Syongari 17165138Syongari#define TIT_MAX_OPERANDS (4) /* maximum number of operands in one 18165138Syongari single tahoe instruction */ 19165138Syongari 20165138Syongaristruct top /* tahoe instruction operand */ 21165138Syongari{ 22165138Syongari int top_ndx; /* -1, or index register. eg 7=[R7] */ 23165138Syongari int top_reg; /* -1, or register number. eg 7 = R7 or (R7) */ 24165138Syongari byte top_mode; /* Addressing mode byte. This byte, defines 25165138Syongari which of the 11 modes opcode is. */ 26165138Syongari 27165138Syongari char top_access; /* Access type wanted for this opperand 28165138Syongari 'b'branch ' 'no-instruction 'amrvw' */ 29165138Syongari char top_width; /* Operand width expected, one of "bwlq?-:!" */ 30165138Syongari 31165138Syongari char *top_error; /* Say if operand is inappropriate */ 32165138Syongari 33165138Syongari segT seg_of_operand; /* segment as returned by expression()*/ 34165138Syongari 35165138Syongari expressionS exp_of_operand; /* The expression as parsed by expression()*/ 36165138Syongari 37165138Syongari byte top_dispsize; /* Number of bytes in the displacement if we 38165138Syongari can figure it out */ 39165138Syongari}; 40165138Syongari 41165138Syongari/* The addressing modes for an operand. These numbers are the acutal values 42165138Syongari for certain modes, so be carefull if you screw with them. */ 43165138Syongari#define TAHOE_DIRECT_REG (0x50) 44165138Syongari#define TAHOE_REG_DEFERRED (0x60) 45165138Syongari 46165138Syongari#define TAHOE_REG_DISP (0xE0) 47165138Syongari#define TAHOE_REG_DISP_DEFERRED (0xF0) 48165138Syongari 49165138Syongari#define TAHOE_IMMEDIATE (0x8F) 50165138Syongari#define TAHOE_IMMEDIATE_BYTE (0x88) 51165138Syongari#define TAHOE_IMMEDIATE_WORD (0x89) 52165138Syongari#define TAHOE_IMMEDIATE_LONGWORD (0x8F) 53165138Syongari#define TAHOE_ABSOLUTE_ADDR (0x9F) 54165138Syongari 55165138Syongari#define TAHOE_DISPLACED_RELATIVE (0xEF) 56165138Syongari#define TAHOE_DISP_REL_DEFERRED (0xFF) 57165138Syongari 58165138Syongari#define TAHOE_AUTO_DEC (0x7E) 59165138Syongari#define TAHOE_AUTO_INC (0x8E) 60165138Syongari#define TAHOE_AUTO_INC_DEFERRED (0x9E) 61165138Syongari/* INDEXED_REG is decided by the existance or lack of a [reg] */ 62165138Syongari 63165138Syongari/* These are encoded into top_width when top_access=='b' 64165138Syongari and it's a psuedo op.*/ 65165138Syongari#define TAHOE_WIDTH_ALWAYS_JUMP '-' 66165138Syongari#define TAHOE_WIDTH_CONDITIONAL_JUMP '?' 67165138Syongari#define TAHOE_WIDTH_BIG_REV_JUMP '!' 68165138Syongari#define TAHOE_WIDTH_BIG_NON_REV_JUMP ':' 69165138Syongari 70165138Syongari/* The hex code for certain tahoe commands and modes. 71165138Syongari This is just for readability. */ 72165138Syongari#define TAHOE_JMP (0x71) 73165138Syongari#define TAHOE_PC_REL_LONG (0xEF) 74165138Syongari#define TAHOE_BRB (0x11) 75165138Syongari#define TAHOE_BRW (0x13) 76165138Syongari/* These, when 'ored' with, or added to, a register number, 77165138Syongari set up the number for the displacement mode. */ 78165138Syongari#define TAHOE_PC_OR_BYTE (0xA0) 79165138Syongari#define TAHOE_PC_OR_WORD (0xC0) 80165138Syongari#define TAHOE_PC_OR_LONG (0xE0) 81165138Syongari 82165138Syongaristruct tit /* get it out of the sewer, it stands for 83165138Syongari tahoe instruction tree (Geeze!) */ 84165138Syongari{ 85165138Syongari tahoe_opcodeT tit_opcode; /* The opcode. */ 86165138Syongari byte tit_operands; /* How many operands are here. */ 87165138Syongari struct top tit_operand[TIT_MAX_OPERANDS]; /* Operands */ 88165138Syongari char *tit_error; /* "" or fatal error text */ 89165138Syongari}; 90165138Syongari 91165138Syongari/* end: tahoe-inst.h */ 92165138Syongari 93165138Syongari/* tahoe.c - tahoe-specific - 94165138Syongari Not part of gas yet. 95165138Syongari */ 96165138Syongari 97165138Syongari#include "opcode/tahoe.h" 98165138Syongari 99165138Syongari/* This is the number to put at the beginning of the a.out file */ 100165138Syongarilong omagic = OMAGIC; 101165138Syongari 102165138Syongari/* These chars start a comment anywhere in a source file (except inside 103165138Syongari another comment or a quoted string. */ 104165138Syongariconst char comment_chars[] = "#;"; 105165138Syongari 106165138Syongari/* These chars only start a comment at the beginning of a line. */ 107165138Syongariconst char line_comment_chars[] = "#"; 108165138Syongari 109165138Syongari/* Chars that can be used to separate mant from exp in floating point nums */ 110165138Syongariconst char EXP_CHARS[] = "eE"; 111165138Syongari 112165138Syongari/* Chars that mean this number is a floating point constant 113165138Syongari as in 0f123.456 114165138Syongari or 0d1.234E-12 (see exp chars above) 115165138Syongari Note: The Tahoe port doesn't support floating point constants. This is 116165138Syongari consistant with 'as' If it's needed, I can always add it later. */ 117165138Syongariconst char FLT_CHARS[] = "df"; 118165138Syongari 119165138Syongari/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be 120165138Syongari changed in read.c . Ideally it shouldn't have to know about it at all, 121165138Syongari but nothing is ideal around here. 122165138Syongari (The tahoe has plenty of room, so the change currently isn't needed.) 123165138Syongari */ 124165138Syongari 125165138Syongaristatic struct tit t; /* A tahoe instruction after decoding. */ 126165138Syongari 127165138Syongarivoid float_cons (); 128165138Syongari/* A table of pseudo ops (sans .), the function called, and an integer op 129165138Syongari that the function is called with. */ 130165138Syongari 131165138Syongariconst pseudo_typeS md_pseudo_table[] = 132165138Syongari{ 133192736Syongari {"dfloat", float_cons, 'd'}, 134192736Syongari {"ffloat", float_cons, 'f'}, 135192736Syongari {0} 136192736Syongari}; 137165138Syongari 138165138Syongari/* 139165138Syongari * For Tahoe, relative addresses of "just the right length" are pretty easy. 140165138Syongari * The branch displacement is always the last operand, even in 141165138Syongari * synthetic instructions. 142193299Syongari * For Tahoe, we encode the relax_substateTs (in e.g. fr_substate) as: 143173775Syongari * 144193299Syongari * 4 3 2 1 0 bit number 145193299Syongari * ---/ /--+-------+-------+-------+-------+-------+ 146165138Syongari * | what state ? | how long ? | 147165138Syongari * ---/ /--+-------+-------+-------+-------+-------+ 148165138Syongari * 149165138Syongari * The "how long" bits are 00=byte, 01=word, 10=long. 150165138Syongari * This is a Un*x convention. 151197592Syongari * Not all lengths are legit for a given value of (what state). 152165138Syongari * The four states are listed below. 153165138Syongari * The "how long" refers merely to the displacement length. 154165138Syongari * The address usually has some constant bytes in it as well. 155165138Syongari * 156165138Syongari 157165138SyongariStates for Tahoe address relaxing. 158165138Syongari1. TAHOE_WIDTH_ALWAYS_JUMP (-) 159165138Syongari Format: "b-" 160165138Syongari Tahoe opcodes are: (Hex) 161165138Syongari jr 11 162165138Syongari jbr 11 163165138Syongari Simple branch. 164165138Syongari Always, 1 byte opcode, then displacement/absolute. 165165138Syongari If word or longword, change opcode to brw or jmp. 166165138Syongari 167165138Syongari 168165138Syongari2. TAHOE_WIDTH_CONDITIONAL_JUMP (?) 169165138Syongari J<cond> where <cond> is a simple flag test. 170165138Syongari Format: "b?" 171165138Syongari Tahoe opcodes are: (Hex) 172165138Syongari jneq/jnequ 21 173165138Syongari jeql/jeqlu 31 174165138Syongari jgtr 41 175165138Syongari jleq 51 176165138Syongari jgeq 81 177165138Syongari jlss 91 178165138Syongari jgtru a1 179165138Syongari jlequ b1 180165138Syongari jvc c1 181165138Syongari jvs d1 182165138Syongari jlssu/jcs e1 183165138Syongari jgequ/jcc f1 184165138Syongari Always, you complement 4th bit to reverse the condition. 185165138Syongari Always, 1-byte opcode, then 1-byte displacement. 186165138Syongari 187165138Syongari3. TAHOE_WIDTH_BIG_REV_JUMP (!) 188165138Syongari Jbc/Jbs where cond tests a memory bit. 189165138Syongari Format: "rlvlb!" 190165138Syongari Tahoe opcodes are: (Hex) 191165138Syongari jbs 0e 192165138Syongari jbc 1e 193165138Syongari Always, you complement 4th bit to reverse the condition. 194165138Syongari Always, 1-byte opcde, longword, longword-address, 1-word-displacement 195165138Syongari 196165138Syongari4. TAHOE_WIDTH_BIG_NON_REV_JUMP (:) 197165138Syongari JaoblXX/Jbssi 198165138Syongari Format: "rlmlb:" 199165138Syongari Tahoe opcodes are: (Hex) 200165138Syongari aojlss 2f 201165138Syongari jaoblss 2f 202165138Syongari aojleq 3f 203165138Syongari jaobleq 3f 204165138Syongari jbssi 5f 205165138Syongari Always, we cannot reverse the sense of the branch; we have a word 206165138Syongari displacement. 207165138Syongari 208165138SyongariWe need to modify the opcode is for class 1, 2 and 3 instructions. 209165138SyongariAfter relax() we may complement the 4th bit of 2 or 3 to reverse sense of 210165138Syongaribranch. 211165138Syongari 212165138SyongariWe sometimes store context in the operand literal. This way we can figure out 213165138Syongariafter relax() what the original addressing mode was. (Was is pc_rel, or 214165138Syongaripc_rel_disp? That sort of thing.) */ 215165138Syongari 216165138Syongari/* These displacements are relative to the START address of the 217165138Syongari displacement which is at the start of the displacement, not the end of 218165138Syongari the instruction. The hardware pc_rel is at the end of the instructions. 219165138Syongari That's why all the displacements have the length of the displacement added 220165138Syongari to them. (WF + length(word)) 221165138Syongari 222165138Syongari The first letter is Byte, Word. 223165138Syongari 2nd letter is Forward, Backward. */ 224165138Syongari#define BF (1+ 127) 225165138Syongari#define BB (1+-128) 226165138Syongari#define WF (2+ 32767) 227165138Syongari#define WB (2+-32768) 228165138Syongari/* Dont need LF, LB because they always reach. [They are coded as 0.] */ 229165138Syongari 230165138Syongari#define C(a,b) ENCODE_RELAX(a,b) 231193293Syongari/* This macro has no side-effects. */ 232193293Syongari#define ENCODE_RELAX(what,length) (((what) << 2) + (length)) 233165138Syongari#define RELAX_STATE(what) ((what) >> 2) 234165138Syongari#define RELAX_LENGTH(length) ((length) && 3) 235165138Syongari 236165138Syongari#define STATE_ALWAYS_BRANCH (1) 237165138Syongari#define STATE_CONDITIONAL_BRANCH (2) 238165138Syongari#define STATE_BIG_REV_BRANCH (3) 239165138Syongari#define STATE_BIG_NON_REV_BRANCH (4) 240165138Syongari#define STATE_PC_RELATIVE (5) 241165138Syongari 242165138Syongari#define STATE_BYTE (0) 243165138Syongari#define STATE_WORD (1) 244165138Syongari#define STATE_LONG (2) 245165138Syongari#define STATE_UNDF (3) /* Symbol undefined in pass1 */ 246165138Syongari 247165138Syongari/* This is the table used by gas to figure out relaxing modes. The fields are 248165138Syongari forward_branch reach, backward_branch reach, number of bytes it would take, 249165138Syongari where the next biggest branch is. */ 250165138Syongariconst relax_typeS md_relax_table[] = 251165138Syongari{ 252165138Syongari { 253165138Syongari 1, 1, 0, 0 254165138Syongari }, /* error sentinel 0,0 */ 255165138Syongari { 256165138Syongari 1, 1, 0, 0 257165138Syongari }, /* unused 0,1 */ 258165138Syongari { 259165138Syongari 1, 1, 0, 0 260165138Syongari }, /* unused 0,2 */ 261165138Syongari { 262165138Syongari 1, 1, 0, 0 263165138Syongari }, /* unused 0,3 */ 264165138Syongari/* Unconditional branch cases "jrb" 265165138Syongari The relax part is the actual displacement */ 266165138Syongari { 267165138Syongari BF, BB, 1, C (1, 1) 268165138Syongari }, /* brb B`foo 1,0 */ 269165138Syongari { 270165138Syongari WF, WB, 2, C (1, 2) 271165138Syongari }, /* brw W`foo 1,1 */ 272165138Syongari { 273165138Syongari 0, 0, 5, 0 274165138Syongari }, /* Jmp L`foo 1,2 */ 275165138Syongari { 276165138Syongari 1, 1, 0, 0 277165138Syongari }, /* unused 1,3 */ 278165138Syongari/* Reversible Conditional Branch. If the branch won't reach, reverse 279165138Syongari it, and jump over a brw or a jmp that will reach. The relax part is the 280165138Syongari actual address. */ 281165138Syongari { 282165138Syongari BF, BB, 1, C (2, 1) 283165138Syongari }, /* b<cond> B`foo 2,0 */ 284165138Syongari { 285165138Syongari WF + 2, WB + 2, 4, C (2, 2) 286165138Syongari }, /* brev over, brw W`foo, over: 2,1 */ 287165138Syongari { 288165138Syongari 0, 0, 7, 0 289165138Syongari }, /* brev over, jmp L`foo, over: 2,2 */ 290165138Syongari { 291165138Syongari 1, 1, 0, 0 292165138Syongari }, /* unused 2,3 */ 293165138Syongari/* Another type of reversable branch. But this only has a word 294165138Syongari displacement. */ 295165138Syongari { 296165138Syongari 1, 1, 0, 0 297165138Syongari }, /* unused 3,0 */ 298165138Syongari { 299165138Syongari WF, WB, 2, C (3, 2) 300165138Syongari }, /* jbX W`foo 3,1 */ 301165138Syongari { 302165138Syongari 0, 0, 8, 0 303165138Syongari }, /* jrevX over, jmp L`foo, over: 3,2 */ 304165138Syongari { 305165138Syongari 1, 1, 0, 0 306165138Syongari }, /* unused 3,3 */ 307165138Syongari/* These are the non reversable branches, all of which have a word 308165138Syongari displacement. If I can't reach, branch over a byte branch, to a 309165138Syongari jump that will reach. The jumped branch jumps over the reaching 310165138Syongari branch, to continue with the flow of the program. It's like playing 311165138Syongari leap frog. */ 312165138Syongari { 313165138Syongari 1, 1, 0, 0 314165138Syongari }, /* unused 4,0 */ 315165138Syongari { 316165138Syongari WF, WB, 2, C (4, 2) 317165138Syongari }, /* aobl_ W`foo 4,1 */ 318165138Syongari { 319165138Syongari 0, 0, 10, 0 320165138Syongari }, /*aobl_ W`hop,br over,hop: jmp L^foo,over 4,2*/ 321165138Syongari { 322165138Syongari 1, 1, 0, 0 323165138Syongari }, /* unused 4,3 */ 324165138Syongari/* Normal displacement mode, no jumping or anything like that. 325165138Syongari The relax points to one byte before the address, thats why all 326165138Syongari the numbers are up by one. */ 327165138Syongari { 328165138Syongari BF + 1, BB + 1, 2, C (5, 1) 329165138Syongari }, /* B^"foo" 5,0 */ 330165138Syongari { 331165138Syongari WF + 1, WB + 1, 3, C (5, 2) 332165138Syongari }, /* W^"foo" 5,1 */ 333193293Syongari { 334193293Syongari 0, 0, 5, 0 335193293Syongari }, /* L^"foo" 5,2 */ 336193293Syongari { 337193293Syongari 1, 1, 0, 0 338193293Syongari }, /* unused 5,3 */ 339193293Syongari}; 340193293Syongari 341193293Syongari#undef C 342193293Syongari#undef BF 343193293Syongari#undef BB 344193293Syongari#undef WF 345193293Syongari#undef WB 346193293Syongari/* End relax stuff */ 347193293Syongari 348193293Syongari/* Handle of the OPCODE hash table. NULL means any use before 349193293Syongari md_begin() will crash. */ 350193293Syongaristatic struct hash_control *op_hash; 351193293Syongari 352193293Syongari/* Init function. Build the hash table. */ 353193293Syongarivoid 354193293Syongarimd_begin () 355193293Syongari{ 356193293Syongari struct tot *tP; 357193293Syongari char *errorval = 0; 358193293Syongari int synthetic_too = 1; /* If 0, just use real opcodes. */ 359193293Syongari 360193293Syongari op_hash = hash_new (); 361193293Syongari 362193293Syongari for (tP = totstrs; *tP->name && !errorval; tP++) 363193293Syongari errorval = hash_insert (op_hash, tP->name, &tP->detail); 364193293Syongari 365193293Syongari if (synthetic_too) 366193293Syongari for (tP = synthetic_totstrs; *tP->name && !errorval; tP++) 367193293Syongari errorval = hash_insert (op_hash, tP->name, &tP->detail); 368193293Syongari 369193293Syongari if (errorval) 370193293Syongari as_fatal (errorval); 371193293Syongari} 372193293Syongari 373193293SyongariCONST char *md_shortopts = "ad:STt:V"; 374193293Syongaristruct option md_longopts[] = { 375193293Syongari {NULL, no_argument, NULL, 0} 376193293Syongari}; 377193293Syongarisize_t md_longopts_size = sizeof(md_longopts); 378193293Syongari 379193293Syongariint 380193293Syongarimd_parse_option (c, arg) 381193293Syongari int c; 382193293Syongari char *arg; 383165138Syongari{ 384165138Syongari switch (c) 385165138Syongari { 386165138Syongari case 'a': 387165138Syongari as_warn (_("The -a option doesn't exist. (Despite what the man page says!")); 388165138Syongari break; 389165138Syongari 390165138Syongari case 'd': 391165138Syongari as_warn (_("Displacement length %s ignored!"), arg); 392165138Syongari break; 393165138Syongari 394165138Syongari case 'S': 395165138Syongari as_warn (_("SYMBOL TABLE not implemented")); 396165138Syongari break; 397165138Syongari 398165138Syongari case 'T': 399165138Syongari as_warn (_("TOKEN TRACE not implemented")); 400165138Syongari break; 401165138Syongari 402165138Syongari case 't': 403165138Syongari as_warn (_("I don't need or use temp. file \"%s\"."), arg); 404165138Syongari break; 405165138Syongari 406165138Syongari case 'V': 407165138Syongari as_warn (_("I don't use an interpass file! -V ignored")); 408165138Syongari break; 409165138Syongari 410165138Syongari default: 411165138Syongari return 0; 412165138Syongari } 413165138Syongari 414165138Syongari return 1; 415165138Syongari} 416165138Syongari 417165138Syongarivoid 418165138Syongarimd_show_usage (stream) 419165138Syongari FILE *stream; 420165138Syongari{ 421165138Syongari fprintf(stream, _("\ 422165138SyongariTahoe options:\n\ 423165138Syongari-a ignored\n\ 424165138Syongari-d LENGTH ignored\n\ 425165138Syongari-J ignored\n\ 426165138Syongari-S ignored\n\ 427165138Syongari-t FILE ignored\n\ 428165138Syongari-T ignored\n\ 429165138Syongari-V ignored\n")); 430165138Syongari} 431165138Syongari 432165138Syongari/* The functions in this section take numbers in the machine format, and 433165138Syongari munges them into Tahoe byte order. 434165138Syongari They exist primarily for cross assembly purpose. */ 435165138Syongarivoid /* Knows about order of bytes in address. */ 436165138Syongarimd_number_to_chars (con, value, nbytes) 437165138Syongari char con[]; /* Return 'nbytes' of chars here. */ 438165138Syongari valueT value; /* The value of the bits. */ 439165138Syongari int nbytes; /* Number of bytes in the output. */ 440165138Syongari{ 441165138Syongari number_to_chars_bigendian (con, value, nbytes); 442165138Syongari} 443165138Syongari 444165138Syongari#ifdef comment 445165138Syongarivoid /* Knows about order of bytes in address. */ 446165138Syongarimd_number_to_imm (con, value, nbytes) 447165138Syongari char con[]; /* Return 'nbytes' of chars here. */ 448165138Syongari long int value; /* The value of the bits. */ 449165138Syongari int nbytes; /* Number of bytes in the output. */ 450165138Syongari{ 451165138Syongari md_number_to_chars (con, value, nbytes); 452165138Syongari} 453165138Syongari 454165138Syongari#endif /* comment */ 455165138Syongari 456165138Syongarivoid 457165138Syongaritc_apply_fix (fixP, val) 458165138Syongari fixS *fixP; 459165138Syongari long val; 460165138Syongari{ 461165138Syongari /* should never be called */ 462165138Syongari know (0); 463165138Syongari} 464165138Syongari 465165138Syongarivoid /* Knows about order of bytes in address. */ 466165138Syongarimd_number_to_disp (con, value, nbytes) 467165138Syongari char con[]; /* Return 'nbytes' of chars here. */ 468165138Syongari long int value; /* The value of the bits. */ 469165138Syongari int nbytes; /* Number of bytes in the output. */ 470165138Syongari{ 471165138Syongari md_number_to_chars (con, value, nbytes); 472165138Syongari} 473165138Syongari 474165138Syongarivoid /* Knows about order of bytes in address. */ 475165138Syongarimd_number_to_field (con, value, nbytes) 476165138Syongari char con[]; /* Return 'nbytes' of chars here. */ 477165138Syongari long int value; /* The value of the bits. */ 478165138Syongari int nbytes; /* Number of bytes in the output. */ 479165138Syongari{ 480165138Syongari md_number_to_chars (con, value, nbytes); 481165138Syongari} 482165138Syongari 483165138Syongari/* Put the bits in an order that a tahoe will understand, despite the ordering 484165138Syongari of the native machine. 485165138Syongari On Tahoe: first 4 bytes are normal unsigned big endian long, 486165138Syongari next three bytes are symbolnum, in kind of 3 byte big endian (least sig. byte last). 487165138Syongari The last byte is broken up with bit 7 as pcrel, 488165138Syongari bits 6 & 5 as length, 489165138Syongari bit 4 as extern and the last nibble as 'undefined'. */ 490165138Syongari 491165138Syongari#if comment 492165138Syongarivoid 493165138Syongarimd_ri_to_chars (ri_p, ri) 494165138Syongari struct relocation_info *ri_p, ri; 495165138Syongari{ 496165138Syongari byte the_bytes[sizeof (struct relocation_info)]; 497165138Syongari /* The reason I can't just encode these directly into ri_p is that 498165138Syongari ri_p may point to ri. */ 499165138Syongari 500165138Syongari /* This is easy */ 501165138Syongari md_number_to_chars (the_bytes, ri.r_address, sizeof (ri.r_address)); 502165138Syongari 503165138Syongari /* now the fun stuff */ 504165138Syongari the_bytes[4] = (ri.r_symbolnum >> 16) & 0x0ff; 505165138Syongari the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff; 506165138Syongari the_bytes[6] = ri.r_symbolnum & 0x0ff; 507165138Syongari the_bytes[7] = (((ri.r_extern << 4) & 0x10) | ((ri.r_length << 5) & 0x60) | 508165138Syongari ((ri.r_pcrel << 7) & 0x80)) & 0xf0; 509165138Syongari 510165138Syongari bcopy (the_bytes, (char *) ri_p, sizeof (struct relocation_info)); 511165138Syongari} 512165138Syongari 513165138Syongari#endif /* comment */ 514165138Syongari 515165138Syongari/* Put the bits in an order that a tahoe will understand, despite the ordering 516165138Syongari of the native machine. 517165138Syongari On Tahoe: first 4 bytes are normal unsigned big endian long, 518165138Syongari next three bytes are symbolnum, in kind of 3 byte big endian (least sig. byte last). 519165138Syongari The last byte is broken up with bit 7 as pcrel, 520165138Syongari bits 6 & 5 as length, 521165138Syongari bit 4 as extern and the last nibble as 'undefined'. */ 522165138Syongari 523165138Syongarivoid 524165138Syongaritc_aout_fix_to_chars (where, fixP, segment_address_in_file) 525165138Syongari char *where; 526165138Syongari fixS *fixP; 527165138Syongari relax_addressT segment_address_in_file; 528165138Syongari{ 529165138Syongari long r_symbolnum; 530165138Syongari 531165138Syongari know (fixP->fx_addsy != NULL); 532165138Syongari 533165138Syongari md_number_to_chars (where, 534165138Syongari fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, 535165138Syongari 4); 536165138Syongari 537165138Syongari r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) 538165138Syongari ? S_GET_TYPE (fixP->fx_addsy) 539165138Syongari : fixP->fx_addsy->sy_number); 540165138Syongari 541165138Syongari where[4] = (r_symbolnum >> 16) & 0x0ff; 542165138Syongari where[5] = (r_symbolnum >> 8) & 0x0ff; 543165138Syongari where[6] = r_symbolnum & 0x0ff; 544165138Syongari where[7] = (((is_pcrel (fixP) << 7) & 0x80) 545165138Syongari | ((((fixP->fx_type == FX_8 || fixP->fx_type == FX_PCREL8 546165138Syongari ? 0 547165138Syongari : (fixP->fx_type == FX_16 || fixP->fx_type == FX_PCREL16 548165138Syongari ? 1 549165138Syongari : (fixP->fx_type == FX_32 || fixP->fx_type == FX_PCREL32 550165138Syongari ? 2 551165138Syongari : 42)))) << 5) & 0x60) 552165138Syongari | ((!S_IS_DEFINED (fixP->fx_addsy) << 4) & 0x10)); 553165138Syongari} 554165138Syongari 555165138Syongari/* Relocate byte stuff */ 556165138Syongari 557165138Syongari/* This is for broken word. */ 558165138Syongariconst int md_short_jump_size = 3; 559165138Syongari 560165138Syongarivoid 561165138Syongarimd_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) 562165138Syongari char *ptr; 563165138Syongari addressT from_addr, to_addr; 564165138Syongari fragS *frag; 565165138Syongari symbolS *to_symbol; 566165138Syongari{ 567165138Syongari valueT offset; 568165138Syongari 569165138Syongari offset = to_addr - (from_addr + 1); 570165138Syongari *ptr++ = TAHOE_BRW; 571165138Syongari md_number_to_chars (ptr, offset, 2); 572165138Syongari} 573165138Syongari 574165138Syongariconst int md_long_jump_size = 6; 575165138Syongariconst int md_reloc_size = 8; /* Size of relocation record */ 576165138Syongari 577165138Syongarivoid 578165138Syongarimd_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) 579165138Syongari char *ptr; 580165138Syongari addressT from_addr, to_addr; 581165138Syongari fragS *frag; 582165138Syongari symbolS *to_symbol; 583165138Syongari{ 584165138Syongari valueT offset; 585165138Syongari 586165138Syongari offset = to_addr - (from_addr + 4); 587165138Syongari *ptr++ = TAHOE_JMP; 588165138Syongari *ptr++ = TAHOE_PC_REL_LONG; 589165138Syongari md_number_to_chars (ptr, offset, 4); 590165138Syongari} 591165138Syongari 592165138Syongari/* 593165138Syongari * md_estimate_size_before_relax() 594165138Syongari * 595165138Syongari * Called just before relax(). 596165138Syongari * Any symbol that is now undefined will not become defined, so we assumed 597165138Syongari * that it will be resolved by the linker. 598165138Syongari * Return the correct fr_subtype in the frag, for relax() 599165138Syongari * Return the initial "guess for fr_var" to caller. (How big I think this 600165138Syongari * will be.) 601165138Syongari * The guess for fr_var is ACTUALLY the growth beyond fr_fix. 602165138Syongari * Whatever we do to grow fr_fix or fr_var contributes to our returned value. 603165138Syongari * Although it may not be explicit in the frag, pretend fr_var starts with a 604165138Syongari * 0 value. 605165138Syongari */ 606165138Syongariint 607165138Syongarimd_estimate_size_before_relax (fragP, segment_type) 608165138Syongari register fragS *fragP; 609165138Syongari segT segment_type; /* N_DATA or N_TEXT. */ 610165138Syongari{ 611165138Syongari register char *p; 612165138Syongari register int old_fr_fix; 613165138Syongari /* int pc_rel; FIXME: remove this */ 614165138Syongari 615165138Syongari old_fr_fix = fragP->fr_fix; 616165138Syongari switch (fragP->fr_subtype) 617165138Syongari { 618165138Syongari case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF): 619165138Syongari if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) 620165138Syongari { 621165138Syongari /* The symbol was in the same segment as the opcode, and it's 622165138Syongari a real pc_rel case so it's a relaxable case. */ 623165138Syongari fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE); 624165138Syongari } 625165138Syongari else 626165138Syongari { 627165138Syongari /* This case is still undefined, so asume it's a long word for the 628165138Syongari linker to fix. */ 629165138Syongari p = fragP->fr_literal + old_fr_fix; 630165138Syongari *p |= TAHOE_PC_OR_LONG; 631165138Syongari /* We now know how big it will be, one long word. */ 632165138Syongari fragP->fr_fix += 1 + 4; 633165138Syongari fix_new (fragP, old_fr_fix + 1, fragP->fr_symbol, 634165138Syongari fragP->fr_offset, FX_PCREL32, NULL); 635165138Syongari frag_wane (fragP); 636165138Syongari } 637165138Syongari break; 638165138Syongari 639165138Syongari case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF): 640165138Syongari if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) 641165138Syongari { 642165138Syongari fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE); 643165138Syongari } 644165138Syongari else 645165138Syongari { 646165138Syongari p = fragP->fr_literal + old_fr_fix; 647165138Syongari *fragP->fr_opcode ^= 0x10; /* Reverse sense of branch. */ 648165138Syongari *p++ = 6; 649165138Syongari *p++ = TAHOE_JMP; 650165138Syongari *p++ = TAHOE_PC_REL_LONG; 651165138Syongari fragP->fr_fix += 1 + 1 + 1 + 4; 652165138Syongari fix_new (fragP, old_fr_fix + 3, fragP->fr_symbol, 653165138Syongari fragP->fr_offset, FX_PCREL32, NULL); 654165138Syongari frag_wane (fragP); 655165138Syongari } 656165138Syongari break; 657165138Syongari 658165138Syongari case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_UNDF): 659165138Syongari if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) 660165138Syongari { 661165138Syongari fragP->fr_subtype = 662165138Syongari ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_WORD); 663165138Syongari } 664165138Syongari else 665165138Syongari { 666165138Syongari p = fragP->fr_literal + old_fr_fix; 667165138Syongari *fragP->fr_opcode ^= 0x10; /* Reverse sense of branch. */ 668165138Syongari *p++ = 0; 669165138Syongari *p++ = 6; 670165138Syongari *p++ = TAHOE_JMP; 671165138Syongari *p++ = TAHOE_PC_REL_LONG; 672165138Syongari fragP->fr_fix += 2 + 2 + 4; 673165138Syongari fix_new (fragP, old_fr_fix + 4, fragP->fr_symbol, 674165138Syongari fragP->fr_offset, FX_PCREL32, NULL); 675165138Syongari frag_wane (fragP); 676165138Syongari } 677165138Syongari break; 678165138Syongari 679193293Syongari case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_UNDF): 680165138Syongari if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) 681165138Syongari { 682165138Syongari fragP->fr_subtype = ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_WORD); 683165138Syongari } 684165138Syongari else 685165138Syongari { 686165138Syongari p = fragP->fr_literal + old_fr_fix; 687165138Syongari *p++ = 2; 688165138Syongari *p++ = 0; 689165138Syongari *p++ = TAHOE_BRB; 690165138Syongari *p++ = 6; 691165138Syongari *p++ = TAHOE_JMP; 692165138Syongari *p++ = TAHOE_PC_REL_LONG; 693165138Syongari fragP->fr_fix += 2 + 2 + 2 + 4; 694165138Syongari fix_new (fragP, old_fr_fix + 6, fragP->fr_symbol, 695165138Syongari fragP->fr_offset, FX_PCREL32, NULL); 696165138Syongari frag_wane (fragP); 697165138Syongari } 698165138Syongari break; 699165138Syongari 700165138Syongari case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF): 701165138Syongari if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) 702165138Syongari { 703165138Syongari fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE); 704165138Syongari } 705165138Syongari else 706165138Syongari { 707165138Syongari p = fragP->fr_literal + old_fr_fix; 708165138Syongari *fragP->fr_opcode = TAHOE_JMP; 709165138Syongari *p++ = TAHOE_PC_REL_LONG; 710165138Syongari fragP->fr_fix += 1 + 4; 711165138Syongari fix_new (fragP, old_fr_fix + 1, fragP->fr_symbol, 712165138Syongari fragP->fr_offset, FX_PCREL32, NULL); 713165138Syongari frag_wane (fragP); 714165138Syongari } 715165138Syongari break; 716165138Syongari 717165138Syongari default: 718165138Syongari break; 719165138Syongari } 720165138Syongari return (fragP->fr_var + fragP->fr_fix - old_fr_fix); 721165138Syongari} /* md_estimate_size_before_relax() */ 722165138Syongari 723165138Syongari/* 724165138Syongari * md_convert_frag(); 725165138Syongari * 726165138Syongari * Called after relax() is finished. 727165138Syongari * In: Address of frag. 728165138Syongari * fr_type == rs_machine_dependent. 729165138Syongari * fr_subtype is what the address relaxed to. 730165138Syongari * 731165138Syongari * Out: Any fixSs and constants are set up. 732165138Syongari * Caller will turn frag into a ".space 0". 733165138Syongari */ 734165138Syongarivoid 735165138Syongarimd_convert_frag (headers, seg, fragP) 736165138Syongari object_headers *headers; 737165138Syongari segT seg; 738165138Syongari register fragS *fragP; 739165138Syongari{ 740165138Syongari register char *addressP; /* -> _var to change. */ 741165138Syongari register char *opcodeP; /* -> opcode char(s) to change. */ 742165138Syongari register short int length_code; /* 2=long 1=word 0=byte */ 743165138Syongari register short int extension = 0; /* Size of relaxed address. 744165138Syongari Added to fr_fix: incl. ALL var chars. */ 745165138Syongari register symbolS *symbolP; 746165138Syongari register long int where; 747165138Syongari register long int address_of_var; 748165138Syongari /* Where, in file space, is _var of *fragP? */ 749165138Syongari register long int target_address; 750165138Syongari /* Where, in file space, does addr point? */ 751165138Syongari 752165138Syongari know (fragP->fr_type == rs_machine_dependent); 753165138Syongari length_code = RELAX_LENGTH (fragP->fr_subtype); 754165138Syongari know (length_code >= 0 && length_code < 3); 755165138Syongari where = fragP->fr_fix; 756165138Syongari addressP = fragP->fr_literal + where; 757165138Syongari opcodeP = fragP->fr_opcode; 758165138Syongari symbolP = fragP->fr_symbol; 759165138Syongari know (symbolP); 760165138Syongari target_address = S_GET_VALUE (symbolP) + fragP->fr_offset; 761165138Syongari address_of_var = fragP->fr_address + where; 762165138Syongari switch (fragP->fr_subtype) 763165138Syongari { 764165138Syongari case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE): 765165138Syongari /* *addressP holds the registers number, plus 0x10, if it's deferred 766165138Syongari mode. To set up the right mode, just OR the size of this displacement */ 767165138Syongari /* Byte displacement. */ 768165138Syongari *addressP++ |= TAHOE_PC_OR_BYTE; 769165138Syongari *addressP = target_address - (address_of_var + 2); 770165138Syongari extension = 2; 771165138Syongari break; 772165138Syongari 773165138Syongari case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD): 774165138Syongari /* Word displacement. */ 775165138Syongari *addressP++ |= TAHOE_PC_OR_WORD; 776165138Syongari md_number_to_chars (addressP, target_address - (address_of_var + 3), 2); 777165138Syongari extension = 3; 778165138Syongari break; 779165138Syongari 780165138Syongari case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_LONG): 781165138Syongari /* Long word displacement. */ 782165138Syongari *addressP++ |= TAHOE_PC_OR_LONG; 783165138Syongari md_number_to_chars (addressP, target_address - (address_of_var + 5), 4); 784165138Syongari extension = 5; 785165138Syongari break; 786165138Syongari 787165138Syongari case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE): 788165138Syongari *addressP = target_address - (address_of_var + 1); 789165138Syongari extension = 1; 790165138Syongari break; 791165138Syongari 792165138Syongari case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD): 793165138Syongari *opcodeP ^= 0x10; /* Reverse sense of test. */ 794165138Syongari *addressP++ = 3; /* Jump over word branch */ 795165138Syongari *addressP++ = TAHOE_BRW; 796165138Syongari md_number_to_chars (addressP, target_address - (address_of_var + 4), 2); 797165138Syongari extension = 4; 798165138Syongari break; 799165138Syongari 800165138Syongari case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_LONG): 801165138Syongari *opcodeP ^= 0x10; /* Reverse sense of test. */ 802165138Syongari *addressP++ = 6; 803165138Syongari *addressP++ = TAHOE_JMP; 804165138Syongari *addressP++ = TAHOE_PC_REL_LONG; 805165138Syongari md_number_to_chars (addressP, target_address, 4); 806165138Syongari extension = 7; 807165138Syongari break; 808165138Syongari 809165138Syongari case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE): 810165138Syongari *addressP = target_address - (address_of_var + 1); 811165138Syongari extension = 1; 812165138Syongari break; 813165138Syongari 814165138Syongari case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD): 815165138Syongari *opcodeP = TAHOE_BRW; 816165138Syongari md_number_to_chars (addressP, target_address - (address_of_var + 2), 2); 817165138Syongari extension = 2; 818165138Syongari break; 819165138Syongari 820165138Syongari case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_LONG): 821165138Syongari *opcodeP = TAHOE_JMP; 822165138Syongari *addressP++ = TAHOE_PC_REL_LONG; 823165138Syongari md_number_to_chars (addressP, target_address - (address_of_var + 5), 4); 824165138Syongari extension = 5; 825165138Syongari break; 826165138Syongari 827165138Syongari case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_WORD): 828165138Syongari md_number_to_chars (addressP, target_address - (address_of_var + 2), 2); 829165138Syongari extension = 2; 830165138Syongari break; 831165138Syongari 832165138Syongari case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_LONG): 833165138Syongari *opcodeP ^= 0x10; 834165138Syongari *addressP++ = 0; 835165138Syongari *addressP++ = 6; 836165138Syongari *addressP++ = TAHOE_JMP; 837165138Syongari *addressP++ = TAHOE_PC_REL_LONG; 838165138Syongari md_number_to_chars (addressP, target_address, 4); 839165138Syongari extension = 8; 840165138Syongari break; 841165138Syongari 842165138Syongari case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_WORD): 843165138Syongari md_number_to_chars (addressP, target_address - (address_of_var + 2), 2); 844165138Syongari extension = 2; 845165138Syongari break; 846165138Syongari 847165138Syongari case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_LONG): 848165138Syongari *addressP++ = 0; 849165138Syongari *addressP++ = 2; 850165138Syongari *addressP++ = TAHOE_BRB; 851165138Syongari *addressP++ = 6; 852165138Syongari *addressP++ = TAHOE_JMP; 853165138Syongari *addressP++ = TAHOE_PC_REL_LONG; 854165138Syongari md_number_to_chars (addressP, target_address, 4); 855165138Syongari extension = 10; 856165138Syongari break; 857165138Syongari 858165138Syongari default: 859165138Syongari BAD_CASE (fragP->fr_subtype); 860165138Syongari break; 861165138Syongari } 862165138Syongari fragP->fr_fix += extension; 863165138Syongari} /* md_convert_frag */ 864165138Syongari 865165138Syongari 866165138Syongari/* This is the stuff for md_assemble. */ 867165138Syongari#define FP_REG 13 868165138Syongari#define SP_REG 14 869165138Syongari#define PC_REG 15 870165138Syongari#define BIGGESTREG PC_REG 871165138Syongari 872165138Syongari/* 873165138Syongari * Parse the string pointed to by START 874165138Syongari * If it represents a valid register, point START to the character after 875165138Syongari * the last valid register char, and return the register number (0-15). 876165138Syongari * If invalid, leave START alone, return -1. 877165138Syongari * The format has to be exact. I don't do things like eat leading zeros 878165138Syongari * or the like. 879165138Syongari * Note: This doesn't check for the next character in the string making 880165138Syongari * this invalid. Ex: R123 would return 12, it's the callers job to check 881165138Syongari * what start is point to apon return. 882165138Syongari * 883165138Syongari * Valid registers are R1-R15, %1-%15, FP (13), SP (14), PC (15) 884165138Syongari * Case doesn't matter. 885165138Syongari */ 886165138Syongariint 887165138Syongaritahoe_reg_parse (start) 888165138Syongari char **start; /* A pointer to the string to parse. */ 889193293Syongari{ 890165138Syongari register char *regpoint = *start; 891165138Syongari register int regnum = -1; 892192734Syongari 893165138Syongari switch (*regpoint++) 894165138Syongari { 895165138Syongari case '%': /* Registers can start with a %, 896165138Syongari R or r, and then a number. */ 897165138Syongari case 'R': 898165138Syongari case 'r': 899165138Syongari if (isdigit (*regpoint)) 900165138Syongari { 901165138Syongari /* Got the first digit. */ 902165138Syongari regnum = *regpoint++ - '0'; 903173769Syongari if ((regnum == 1) && isdigit (*regpoint)) 904173769Syongari { 905165138Syongari /* Its a two digit number. */ 906192734Syongari regnum = 10 + (*regpoint++ - '0'); 907192734Syongari if (regnum > BIGGESTREG) 908193293Syongari { /* Number too big? */ 909193293Syongari regnum = -1; 910193293Syongari } 911165138Syongari } 912165138Syongari } 913165138Syongari break; 914165138Syongari case 'F': /* Is it the FP */ 915165138Syongari case 'f': 916165138Syongari switch (*regpoint++) 917165138Syongari { 918165138Syongari case 'p': 919165138Syongari case 'P': 920165138Syongari regnum = FP_REG; 921165138Syongari } 922165138Syongari break; 923165138Syongari case 's': /* How about the SP */ 924165138Syongari case 'S': 925165138Syongari switch (*regpoint++) 926165138Syongari { 927165138Syongari case 'p': 928165138Syongari case 'P': 929165138Syongari regnum = SP_REG; 930165138Syongari } 931165138Syongari break; 932165138Syongari case 'p': /* OR the PC even */ 933165138Syongari case 'P': 934165138Syongari switch (*regpoint++) 935165138Syongari { 936165138Syongari case 'c': 937165138Syongari case 'C': 938165138Syongari regnum = PC_REG; 939165138Syongari } 940165138Syongari break; 941165138Syongari } 942165138Syongari 943165138Syongari if (regnum != -1) 944165138Syongari { /* No error, so move string pointer */ 945165138Syongari *start = regpoint; 946165138Syongari } 947165138Syongari return regnum; /* Return results */ 948165138Syongari} /* tahoe_reg_parse */ 949165138Syongari 950165138Syongari/* 951165138Syongari * This chops up an operand and figures out its modes and stuff. 952165138Syongari * It's a little touchy about extra characters. 953165138Syongari * Optex to start with one extra character so it can be overwritten for 954165138Syongari * the backward part of the parsing. 955165138Syongari * You can't put a bunch of extra characters in side to 956165138Syongari * make the command look cute. ie: * foo ( r1 ) [ r0 ] 957165138Syongari * If you like doing a lot of typing, try COBOL! 958165138Syongari * Actually, this parser is a little weak all around. It's designed to be 959165138Syongari * used with compliers, so I emphisise correct decoding of valid code quickly 960165138Syongari * rather that catching every possable error. 961165138Syongari * Note: This uses the expression function, so save input_line_pointer before 962165138Syongari * calling. 963165138Syongari * 964165138Syongari * Sperry defines the semantics of address modes (and values) 965165138Syongari * by a two-letter code, explained here. 966165138Syongari * 967165138Syongari * letter 1: access type 968165138Syongari * 969165138Syongari * a address calculation - no data access, registers forbidden 970165138Syongari * b branch displacement 971165138Syongari * m read - let go of bus - write back "modify" 972165138Syongari * r read 973165138Syongari * w write 974165138Syongari * v bit field address: like 'a' but registers are OK 975193293Syongari * 976193293Syongari * letter 2: data type (i.e. width, alignment) 977193293Syongari * 978193293Syongari * b byte 979193293Syongari * w word 980193293Syongari * l longword 981193293Syongari * q quadword (Even regs < 14 allowed) (if 12, you get a warning) 982193293Syongari * - unconditional synthetic jbr operand 983193293Syongari * ? simple synthetic reversable branch operand 984193293Syongari * ! complex synthetic reversable branch operand 985193293Syongari * : complex synthetic non-reversable branch operand 986193293Syongari * 987165138Syongari * The '-?!:' letter 2's are not for external consumption. They are used 988165138Syongari * by GAS for psuedo ops relaxing code. 989165138Syongari * 990165138Syongari * After parsing topP has: 991165138Syongari * 992165138Syongari * top_ndx: -1, or the index register. eg 7=[R7] 993165138Syongari * top_reg: -1, or register number. eg 7 = R7 or (R7) 994165138Syongari * top_mode: The addressing mode byte. This byte, defines which of 995165138Syongari * the 11 modes opcode is. 996165138Syongari * top_access: Access type wanted for this opperand 'b'branch ' ' 997165138Syongari * no-instruction 'amrvw' 998165138Syongari * top_width: Operand width expected, one of "bwlq?-:!" 999165138Syongari * exp_of_operand: The expression as parsed by expression() 1000165138Syongari * top_dispsize: Number of bytes in the displacement if we can figure it 1001165138Syongari * out and it's relavent. 1002165138Syongari * 1003165138Syongari * Need syntax checks built. 1004165138Syongari */ 1005165138Syongari 1006165138Syongarivoid 1007165138Syongaritip_op (optex, topP) 1008165138Syongari char *optex; /* The users text input, with one leading character */ 1009165138Syongari struct top *topP; /* The tahoe instruction with some fields already set: 1010165138Syongari in: access, width 1011165138Syongari out: ndx, reg, mode, error, dispsize */ 1012165138Syongari 1013165138Syongari{ 1014165138Syongari int mode = 0; /* This operand's mode. */ 1015165138Syongari char segfault = *optex; /* To keep the back parsing from freaking. */ 1016165138Syongari char *point = optex + 1; /* Parsing from front to back. */ 1017165138Syongari char *end; /* Parsing from back to front. */ 1018165138Syongari int reg = -1; /* major register, -1 means absent */ 1019165138Syongari int imreg = -1; /* Major register in immediate mode */ 1020165138Syongari int ndx = -1; /* index register number, -1 means absent */ 1021165138Syongari char dec_inc = ' '; /* Is the SP auto-incremented '+' or 1022165138Syongari auto-decremented '-' or neither ' '. */ 1023165138Syongari int immediate = 0; /* 1 if '$' immediate mode */ 1024165138Syongari int call_width = 0; /* If the caller casts the displacement */ 1025165138Syongari int abs_width = 0; /* The width of the absolute displacment */ 1026165138Syongari int com_width = 0; /* Displacement width required by branch */ 1027165138Syongari int deferred = 0; /* 1 if '*' deferral is used */ 1028165138Syongari byte disp_size = 0; /* How big is this operand. 0 == don't know */ 1029165138Syongari char *op_bad = ""; /* Bad operand error */ 1030165138Syongari 1031165138Syongari char *tp, *temp, c; /* Temporary holders */ 1032165138Syongari 1033165138Syongari char access = topP->top_access; /* Save on a deref. */ 1034165138Syongari char width = topP->top_width; 1035165138Syongari 1036165138Syongari int really_none = 0; /* Empty expressions evaluate to 0 1037165138Syongari but I need to know if it's there or not */ 1038165138Syongari expressionS *expP; /* -> expression values for this operand */ 1039165138Syongari 1040165138Syongari /* Does this command restrict the displacement size. */ 1041165138Syongari if (access == 'b') 1042165138Syongari com_width = (width == 'b' ? 1 : 1043165138Syongari (width == 'w' ? 2 : 1044165138Syongari (width == 'l' ? 4 : 0))); 1045165138Syongari 1046165138Syongari *optex = '\0'; /* This is kind of a back stop for all 1047165138Syongari the searches to fail on if needed.*/ 1048165138Syongari if (*point == '*') 1049165138Syongari { /* A dereference? */ 1050165138Syongari deferred = 1; 1051165138Syongari point++; 1052165138Syongari } 1053165138Syongari 1054165138Syongari /* Force words into a certain mode */ 1055165138Syongari /* Bitch, Bitch, Bitch! */ 1056165138Syongari /* 1057165138Syongari * Using the ^ operator is ambigous. If I have an absolute label 1058165138Syongari * called 'w' set to, say 2, and I have the expression 'w^1', do I get 1059165138Syongari * 1, forced to be in word displacement mode, or do I get the value of 1060165138Syongari * 'w' or'ed with 1 (3 in this case). 1061165138Syongari * The default is 'w' as an offset, so that's what I use. 1062165138Syongari * Stick with `, it does the same, and isn't ambig. 1063165138Syongari */ 1064165138Syongari 1065165138Syongari if (*point != '\0' && ((point[1] == '^') || (point[1] == '`'))) 1066165138Syongari switch (*point) 1067165138Syongari { 1068165138Syongari case 'b': 1069165138Syongari case 'B': 1070165138Syongari case 'w': 1071165138Syongari case 'W': 1072165138Syongari case 'l': 1073165138Syongari case 'L': 1074165138Syongari if (com_width) 1075165138Syongari as_warn (_("Casting a branch displacement is bad form, and is ignored.")); 1076165138Syongari else 1077165138Syongari { 1078165138Syongari c = (isupper (*point) ? tolower (*point) : *point); 1079165138Syongari call_width = ((c == 'b') ? 1 : 1080165138Syongari ((c == 'w') ? 2 : 4)); 1081165138Syongari } 1082165138Syongari point += 2; 1083165138Syongari break; 1084165138Syongari } 1085165138Syongari 1086165138Syongari /* Setting immediate mode */ 1087165138Syongari if (*point == '$') 1088165138Syongari { 1089165138Syongari immediate = 1; 1090165138Syongari point++; 1091165138Syongari } 1092165138Syongari 1093165138Syongari /* 1094165138Syongari * I've pulled off all the easy stuff off the front, move to the end and 1095165138Syongari * yank. 1096165138Syongari */ 1097165138Syongari 1098165138Syongari for (end = point; *end != '\0'; end++) /* Move to the end. */ 1099165138Syongari ; 1100165138Syongari 1101165138Syongari if (end != point) /* Null string? */ 1102165138Syongari end--; 1103165138Syongari 1104165138Syongari if (end > point && *end == ' ' && end[-1] != '\'') 1105165138Syongari end--; /* Hop white space */ 1106165138Syongari 1107165138Syongari /* Is this an index reg. */ 1108193293Syongari if ((*end == ']') && (end[-1] != '\'')) 1109193293Syongari { 1110193293Syongari temp = end; 1111193293Syongari 1112193293Syongari /* Find opening brace. */ 1113193293Syongari for (--end; (*end != '[' && end != point); end--) 1114193293Syongari ; 1115193293Syongari 1116193293Syongari /* If I found the opening brace, get the index register number. */ 1117193293Syongari if (*end == '[') 1118165138Syongari { 1119165138Syongari tp = end + 1; /* tp should point to the start of a reg. */ 1120165138Syongari ndx = tahoe_reg_parse (&tp); 1121165138Syongari if (tp != temp) 1122165138Syongari { /* Reg. parse error. */ 1123165138Syongari ndx = -1; 1124165138Syongari } 1125165138Syongari else 1126165138Syongari { 1127165138Syongari end--; /* Found it, move past brace. */ 1128165138Syongari } 1129165138Syongari if (ndx == -1) 1130165138Syongari { 1131165138Syongari op_bad = _("Couldn't parse the [index] in this operand."); 1132165138Syongari end = point; /* Force all the rest of the tests to fail. */ 1133165138Syongari } 1134165138Syongari } 1135165138Syongari else 1136165138Syongari { 1137165138Syongari op_bad = _("Couldn't find the opening '[' for the index of this operand."); 1138165138Syongari end = point; /* Force all the rest of the tests to fail. */ 1139165138Syongari } 1140165138Syongari } 1141165138Syongari 1142165138Syongari /* Post increment? */ 1143165138Syongari if (*end == '+') 1144165138Syongari { 1145165138Syongari dec_inc = '+'; 1146165138Syongari /* was: *end--; */ 1147165138Syongari end--; 1148165138Syongari } 1149165138Syongari 1150165138Syongari /* register in parens? */ 1151165138Syongari if ((*end == ')') && (end[-1] != '\'')) 1152165138Syongari { 1153165138Syongari temp = end; 1154165138Syongari 1155165138Syongari /* Find opening paren. */ 1156165138Syongari for (--end; (*end != '(' && end != point); end--) 1157165138Syongari ; 1158165138Syongari 1159165138Syongari /* If I found the opening paren, get the register number. */ 1160165138Syongari if (*end == '(') 1161165138Syongari { 1162165138Syongari tp = end + 1; 1163165138Syongari reg = tahoe_reg_parse (&tp); 1164165138Syongari if (tp != temp) 1165165138Syongari { 1166165138Syongari /* Not a register, but could be part of the expression. */ 1167165138Syongari reg = -1; 1168165138Syongari end = temp; /* Rest the pointer back */ 1169173769Syongari } 1170165138Syongari else 1171173769Syongari { 1172165138Syongari end--; /* Found the reg. move before opening paren. */ 1173165138Syongari } 1174165138Syongari } 1175165138Syongari else 1176165138Syongari { 1177165138Syongari op_bad = _("Couldn't find the opening '(' for the deref of this operand."); 1178165138Syongari end = point; /* Force all the rest of the tests to fail. */ 1179165138Syongari } 1180165138Syongari } 1181165138Syongari 1182165138Syongari /* Pre decrement? */ 1183165138Syongari if (*end == '-') 1184165138Syongari { 1185165138Syongari if (dec_inc != ' ') 1186165138Syongari { 1187165138Syongari op_bad = _("Operand can't be both pre-inc and post-dec."); 1188165138Syongari end = point; 1189165138Syongari } 1190165138Syongari else 1191165138Syongari { 1192165138Syongari dec_inc = '-'; 1193165138Syongari /* was: *end--; */ 1194165138Syongari end--; 1195165138Syongari } 1196165138Syongari } 1197165138Syongari 1198165138Syongari /* 1199165138Syongari * Everything between point and end is the 'expression', unless it's 1200165138Syongari * a register name. 1201165138Syongari */ 1202165138Syongari 1203165138Syongari c = end[1]; 1204165138Syongari end[1] = '\0'; 1205165138Syongari 1206165138Syongari tp = point; 1207165138Syongari imreg = tahoe_reg_parse (&point); /* Get the immediate register 1208165138Syongari if it is there.*/ 1209165138Syongari if (*point != '\0') 1210165138Syongari { 1211165138Syongari /* If there is junk after point, then the it's not immediate reg. */ 1212165138Syongari point = tp; 1213165138Syongari imreg = -1; 1214165138Syongari } 1215165138Syongari 1216165138Syongari if (imreg != -1 && reg != -1) 1217165138Syongari op_bad = _("I parsed 2 registers in this operand."); 1218165138Syongari 1219165138Syongari /* 1220165138Syongari * Evaluate whats left of the expression to see if it's valid. 1221165138Syongari * Note again: This assumes that the calling expression has saved 1222165138Syongari * input_line_pointer. (Nag, nag, nag!) 1223165138Syongari */ 1224165138Syongari 1225165138Syongari if (*op_bad == '\0') 1226165138Syongari { 1227165138Syongari /* statement has no syntax goofs yet: lets sniff the expression */ 1228165138Syongari input_line_pointer = point; 1229165138Syongari expP = &(topP->exp_of_operand); 1230165138Syongari topP->seg_of_operand = expression (expP); 1231165138Syongari switch (expP->X_op) 1232165138Syongari { 1233165138Syongari case O_absent: 1234165138Syongari /* No expression. For BSD4.2 compatibility, missing expression is 1235165138Syongari absolute 0 */ 1236165138Syongari expP->X_op = O_constant; 1237165138Syongari expP->X_add_number = 0; 1238165138Syongari really_none = 1; 1239165138Syongari case O_constant: 1240165138Syongari /* for SEG_ABSOLUTE, we shouldnt need to set X_op_symbol, 1241165138Syongari X_add_symbol to any particular value. */ 1242165138Syongari /* But, we will program defensively. Since this situation occurs 1243165138Syongari rarely so it costs us little to do so. */ 1244165138Syongari expP->X_add_symbol = NULL; 1245165138Syongari expP->X_op_symbol = NULL; 1246165138Syongari /* How many bytes are needed to express this abs value? */ 1247165138Syongari abs_width = 1248165138Syongari ((((expP->X_add_number & 0xFFFFFF80) == 0) || 1249165138Syongari ((expP->X_add_number & 0xFFFFFF80) == 0xFFFFFF80)) ? 1 : 1250165138Syongari (((expP->X_add_number & 0xFFFF8000) == 0) || 1251165138Syongari ((expP->X_add_number & 0xFFFF8000) == 0xFFFF8000)) ? 2 : 4); 1252165138Syongari 1253165138Syongari case O_symbol: 1254165138Syongari break; 1255165138Syongari 1256165138Syongari default: 1257165138Syongari /* 1258165138Syongari * Major bug. We can't handle the case of a operator 1259165138Syongari * expression in a synthetic opcode variable-length 1260165138Syongari * instruction. We don't have a frag type that is smart 1261165138Syongari * enough to relax a operator, and so we just force all 1262165138Syongari * operators to behave like SEG_PASS1s. Clearly, if there is 1263165138Syongari * a demand we can invent a new or modified frag type and 1264165138Syongari * then coding up a frag for this case will be easy. 1265165138Syongari */ 1266165138Syongari need_pass_2 = 1; 1267165138Syongari op_bad = _("Can't relocate expression error."); 1268165138Syongari break; 1269165138Syongari 1270165138Syongari case O_big: 1271165138Syongari /* This is an error. Tahoe doesn't allow any expressions 1272165138Syongari bigger that a 32 bit long word. Any bigger has to be referenced 1273165138Syongari by address. */ 1274165138Syongari op_bad = _("Expression is too large for a 32 bits."); 1275165138Syongari break; 1276165138Syongari } 1277165138Syongari if (*input_line_pointer != '\0') 1278165138Syongari { 1279165138Syongari op_bad = _("Junk at end of expression."); 1280165138Syongari } 1281165138Syongari } 1282165138Syongari 1283165138Syongari end[1] = c; 1284165138Syongari 1285165138Syongari /* I'm done, so restore optex */ 1286165138Syongari *optex = segfault; 1287165138Syongari 1288165138Syongari 1289165138Syongari /* 1290165138Syongari * At this point in the game, we (in theory) have all the components of 1291165138Syongari * the operand at least parsed. Now it's time to check for syntax/semantic 1292165138Syongari * errors, and build the mode. 1293165138Syongari * This is what I have: 1294165138Syongari * deferred = 1 if '*' 1295165138Syongari * call_width = 0,1,2,4 1296165138Syongari * abs_width = 0,1,2,4 1297165138Syongari * com_width = 0,1,2,4 1298165138Syongari * immediate = 1 if '$' 1299165138Syongari * ndx = -1 or reg num 1300165138Syongari * dec_inc = '-' or '+' or ' ' 1301165138Syongari * reg = -1 or reg num 1302165138Syongari * imreg = -1 or reg num 1303165138Syongari * topP->exp_of_operand 1304165138Syongari * really_none 1305165138Syongari */ 1306165138Syongari /* Is there a displacement size? */ 1307165138Syongari disp_size = (call_width ? call_width : 1308165138Syongari (com_width ? com_width : 1309165138Syongari abs_width ? abs_width : 0)); 1310165138Syongari 1311165138Syongari if (*op_bad == '\0') 1312165138Syongari { 1313165138Syongari if (imreg != -1) 1314165138Syongari { 1315165138Syongari /* Rn */ 1316165138Syongari mode = TAHOE_DIRECT_REG; 1317165138Syongari if (deferred || immediate || (dec_inc != ' ') || 1318165138Syongari (reg != -1) || !really_none) 1319165138Syongari op_bad = _("Syntax error in direct register mode."); 1320165138Syongari else if (ndx != -1) 1321165138Syongari op_bad = _("You can't index a register in direct register mode."); 1322165138Syongari else if (imreg == SP_REG && access == 'r') 1323165138Syongari op_bad = 1324165138Syongari _("SP can't be the source operand with direct register addressing."); 1325165138Syongari else if (access == 'a') 1326165138Syongari op_bad = _("Can't take the address of a register."); 1327165138Syongari else if (access == 'b') 1328165138Syongari op_bad = _("Direct Register can't be used in a branch."); 1329165138Syongari else if (width == 'q' && ((imreg % 2) || (imreg > 13))) 1330165138Syongari op_bad = _("For quad access, the register must be even and < 14."); 1331165138Syongari else if (call_width) 1332165138Syongari op_bad = _("You can't cast a direct register."); 1333165138Syongari 1334165138Syongari if (*op_bad == '\0') 1335165138Syongari { 1336165138Syongari /* No errors, check for warnings */ 1337165138Syongari if (width == 'q' && imreg == 12) 1338165138Syongari as_warn (_("Using reg 14 for quadwords can tromp the FP register.")); 1339165138Syongari 1340165138Syongari reg = imreg; 1341165138Syongari } 1342165138Syongari 1343165138Syongari /* We know: imm = -1 */ 1344165138Syongari } 1345165138Syongari else if (dec_inc == '-') 1346165138Syongari { 1347165138Syongari /* -(SP) */ 1348165138Syongari mode = TAHOE_AUTO_DEC; 1349165138Syongari if (deferred || immediate || !really_none) 1350165138Syongari op_bad = _("Syntax error in auto-dec mode."); 1351165138Syongari else if (ndx != -1) 1352165138Syongari op_bad = _("You can't have an index auto dec mode."); 1353165138Syongari else if (access == 'r') 1354165138Syongari op_bad = _("Auto dec mode cant be used for reading."); 1355165138Syongari else if (reg != SP_REG) 1356165138Syongari op_bad = _("Auto dec only works of the SP register."); 1357165138Syongari else if (access == 'b') 1358165138Syongari op_bad = _("Auto dec can't be used in a branch."); 1359165138Syongari else if (width == 'q') 1360165138Syongari op_bad = _("Auto dec won't work with quadwords."); 1361165138Syongari 1362165138Syongari /* We know: imm = -1, dec_inc != '-' */ 1363165138Syongari } 1364165138Syongari else if (dec_inc == '+') 1365165138Syongari { 1366165138Syongari if (immediate || !really_none) 1367165138Syongari op_bad = _("Syntax error in one of the auto-inc modes."); 1368165138Syongari else if (deferred) 1369165138Syongari { 1370165138Syongari /* *(SP)+ */ 1371165138Syongari mode = TAHOE_AUTO_INC_DEFERRED; 1372165138Syongari if (reg != SP_REG) 1373165138Syongari op_bad = _("Auto inc deferred only works of the SP register."); 1374165138Syongari else if (ndx != -1) 1375165138Syongari op_bad = _("You can't have an index auto inc deferred mode."); 1376165138Syongari else if (access == 'b') 1377165138Syongari op_bad = _("Auto inc can't be used in a branch."); 1378165138Syongari } 1379165138Syongari else 1380165138Syongari { 1381165138Syongari /* (SP)+ */ 1382165138Syongari mode = TAHOE_AUTO_INC; 1383165138Syongari if (access == 'm' || access == 'w') 1384165138Syongari op_bad = _("You can't write to an auto inc register."); 1385165138Syongari else if (reg != SP_REG) 1386165138Syongari op_bad = _("Auto inc only works of the SP register."); 1387165138Syongari else if (access == 'b') 1388165138Syongari op_bad = _("Auto inc can't be used in a branch."); 1389165138Syongari else if (width == 'q') 1390165138Syongari op_bad = _("Auto inc won't work with quadwords."); 1391165138Syongari else if (ndx != -1) 1392165138Syongari op_bad = _("You can't have an index in auto inc mode."); 1393165138Syongari } 1394165138Syongari 1395165138Syongari /* We know: imm = -1, dec_inc == ' ' */ 1396165138Syongari } 1397165138Syongari else if (reg != -1) 1398165138Syongari { 1399165138Syongari if ((ndx != -1) && (reg == SP_REG)) 1400165138Syongari op_bad = _("You can't index the sp register."); 1401165138Syongari if (deferred) 1402165138Syongari { 1403165138Syongari /* *<disp>(Rn) */ 1404165138Syongari mode = TAHOE_REG_DISP_DEFERRED; 1405165138Syongari if (immediate) 1406165138Syongari op_bad = _("Syntax error in register displaced mode."); 1407165138Syongari } 1408165138Syongari else if (really_none) 1409165138Syongari { 1410165138Syongari /* (Rn) */ 1411165138Syongari mode = TAHOE_REG_DEFERRED; 1412165138Syongari /* if reg = SP then cant be indexed */ 1413165138Syongari } 1414165138Syongari else 1415165138Syongari { 1416165138Syongari /* <disp>(Rn) */ 1417165138Syongari mode = TAHOE_REG_DISP; 1418165138Syongari } 1419165138Syongari 1420165138Syongari /* We know: imm = -1, dec_inc == ' ', Reg = -1 */ 1421165138Syongari } 1422165138Syongari else 1423165138Syongari { 1424165138Syongari if (really_none) 1425165138Syongari op_bad = _("An offest is needed for this operand."); 1426165138Syongari if (deferred && immediate) 1427165138Syongari { 1428165138Syongari /* *$<ADDR> */ 1429165138Syongari mode = TAHOE_ABSOLUTE_ADDR; 1430165138Syongari disp_size = 4; 1431165138Syongari } 1432165138Syongari else if (immediate) 1433165138Syongari { 1434165138Syongari /* $<disp> */ 1435165138Syongari mode = TAHOE_IMMEDIATE; 1436165138Syongari if (ndx != -1) 1437165138Syongari op_bad = _("You can't index a register in immediate mode."); 1438165138Syongari if (access == 'a') 1439165138Syongari op_bad = _("Immediate access can't be used as an address."); 1440165138Syongari /* ponder the wisdom of a cast because it doesn't do any good. */ 1441165138Syongari } 1442165138Syongari else if (deferred) 1443165138Syongari { 1444165138Syongari /* *<disp> */ 1445165138Syongari mode = TAHOE_DISP_REL_DEFERRED; 1446165138Syongari } 1447165138Syongari else 1448165138Syongari { 1449165138Syongari /* <disp> */ 1450165138Syongari mode = TAHOE_DISPLACED_RELATIVE; 1451165138Syongari } 1452165138Syongari } 1453165138Syongari } 1454165138Syongari 1455165138Syongari /* 1456165138Syongari * At this point, all the errors we can do have be checked for. 1457165138Syongari * We can build the 'top'. */ 1458165138Syongari 1459165138Syongari topP->top_ndx = ndx; 1460165138Syongari topP->top_reg = reg; 1461165138Syongari topP->top_mode = mode; 1462165138Syongari topP->top_error = op_bad; 1463165138Syongari topP->top_dispsize = disp_size; 1464165138Syongari} /* tip_op */ 1465165138Syongari 1466165138Syongari/* 1467165138Syongari * t i p ( ) 1468165138Syongari * 1469165138Syongari * This converts a string into a tahoe instruction. 1470165138Syongari * The string must be a bare single instruction in tahoe (with BSD4 frobs) 1471165138Syongari * format. 1472165138Syongari * It provides at most one fatal error message (which stops the scan) 1473165138Syongari * some warning messages as it finds them. 1474165138Syongari * The tahoe instruction is returned in exploded form. 1475165138Syongari * 1476165138Syongari * The exploded instruction is returned to a struct tit of your choice. 1477165138Syongari * #include "tahoe-inst.h" to know what a struct tit is. 1478165138Syongari * 1479165138Syongari */ 1480165138Syongari 1481165138Syongaristatic void 1482165138Syongaritip (titP, instring) 1483165138Syongari struct tit *titP; /* We build an exploded instruction here. */ 1484165138Syongari char *instring; /* Text of a vax instruction: we modify. */ 1485165138Syongari{ 1486165138Syongari register struct tot_wot *twP = NULL; /* How to bit-encode this opcode. */ 1487165138Syongari register char *p; /* 1/skip whitespace.2/scan vot_how */ 1488165138Syongari register char *q; /* */ 1489165138Syongari register unsigned char count; /* counts number of operands seen */ 1490165138Syongari register struct top *operandp;/* scan operands in struct tit */ 1491165138Syongari register char *alloperr = ""; /* error over all operands */ 1492165138Syongari register char c; /* Remember char, (we clobber it 1493165138Syongari with '\0' temporarily). */ 1494165138Syongari char *save_input_line_pointer; 1495165138Syongari 1496165138Syongari if (*instring == ' ') 1497165138Syongari ++instring; /* Skip leading whitespace. */ 1498165138Syongari for (p = instring; *p && *p != ' '; p++) 1499165138Syongari ; /* MUST end in end-of-string or 1500165138Syongari exactly 1 space. */ 1501165138Syongari /* Scanned up to end of operation-code. */ 1502165138Syongari /* Operation-code is ended with whitespace. */ 1503165138Syongari if (p == instring) 1504165138Syongari { 1505165138Syongari titP->tit_error = _("No operator"); 1506165138Syongari count = 0; 1507165138Syongari titP->tit_opcode = 0; 1508165138Syongari } 1509165138Syongari else 1510165138Syongari { 1511165138Syongari c = *p; 1512165138Syongari *p = '\0'; 1513165138Syongari /* 1514165138Syongari * Here with instring pointing to what better be an op-name, and p 1515165138Syongari * pointing to character just past that. 1516165138Syongari * We trust instring points to an op-name, with no whitespace. 1517165138Syongari */ 1518165138Syongari twP = (struct tot_wot *) hash_find (op_hash, instring); 1519165138Syongari *p = c; /* Restore char after op-code. */ 1520165138Syongari if (twP == 0) 1521165138Syongari { 1522165138Syongari titP->tit_error = _("Unknown operator"); 1523165138Syongari count = 0; 1524165138Syongari titP->tit_opcode = 0; 1525165138Syongari } 1526165138Syongari else 1527165138Syongari { 1528165138Syongari /* 1529165138Syongari * We found a match! So lets pick up as many operands as the 1530165138Syongari * instruction wants, and even gripe if there are too many. 1531165138Syongari * We expect comma to seperate each operand. 1532165138Syongari * We let instring track the text, while p tracks a part of the 1533165138Syongari * struct tot. 1534165138Syongari */ 1535165138Syongari 1536165138Syongari count = 0; /* no operands seen yet */ 1537165138Syongari instring = p + (*p != '\0'); /* point past the operation code */ 1538165138Syongari /* tip_op() screws with the input_line_pointer, so save it before 1539165138Syongari I jump in */ 1540165138Syongari save_input_line_pointer = input_line_pointer; 1541165138Syongari for (p = twP->args, operandp = titP->tit_operand; 1542165138Syongari !*alloperr && *p; 1543165138Syongari operandp++, p += 2) 1544165138Syongari { 1545165138Syongari /* 1546165138Syongari * Here to parse one operand. Leave instring pointing just 1547165138Syongari * past any one ',' that marks the end of this operand. 1548165138Syongari */ 1549165138Syongari if (!p[1]) 1550165138Syongari as_fatal (_("Compiler bug: ODD number of bytes in arg structure %s."), 1551165138Syongari twP->args); 1552165138Syongari else if (*instring) 1553165138Syongari { 1554165138Syongari for (q = instring; (*q != ',' && *q != '\0'); q++) 1555165138Syongari { 1556165138Syongari if (*q == '\'' && q[1] != '\0') /* Jump quoted characters */ 1557165138Syongari q++; 1558165138Syongari } 1559165138Syongari c = *q; 1560165138Syongari /* 1561165138Syongari * Q points to ',' or '\0' that ends argument. C is that 1562165138Syongari * character. 1563165138Syongari */ 1564165138Syongari *q = '\0'; 1565165138Syongari operandp->top_access = p[0]; 1566165138Syongari operandp->top_width = p[1]; 1567165138Syongari tip_op (instring - 1, operandp); 1568165138Syongari *q = c; /* Restore input text. */ 1569165138Syongari if (*(operandp->top_error)) 1570165138Syongari { 1571165138Syongari alloperr = operandp->top_error; 1572165138Syongari } 1573165138Syongari instring = q + (c ? 1 : 0); /* next operand (if any) */ 1574165138Syongari count++; /* won another argument, may have an operr */ 1575165138Syongari } 1576165138Syongari else 1577165138Syongari alloperr = _("Not enough operands"); 1578165138Syongari } 1579165138Syongari /* Restore the pointer. */ 1580165138Syongari input_line_pointer = save_input_line_pointer; 1581165138Syongari 1582165138Syongari if (!*alloperr) 1583165138Syongari { 1584165138Syongari if (*instring == ' ') 1585165138Syongari instring++; /* Skip whitespace. */ 1586165138Syongari if (*instring) 1587165138Syongari alloperr = _("Too many operands"); 1588165138Syongari } 1589165138Syongari titP->tit_error = alloperr; 1590165138Syongari } 1591165138Syongari } 1592165138Syongari 1593165138Syongari titP->tit_opcode = twP->code; /* The op-code. */ 1594165138Syongari titP->tit_operands = count; 1595165138Syongari} /* tip */ 1596165138Syongari 1597165138Syongari/* md_assemble() emit frags for 1 instruction */ 1598165138Syongarivoid 1599165138Syongarimd_assemble (instruction_string) 1600165138Syongari char *instruction_string; /* A string: assemble 1 instruction. */ 1601165138Syongari{ 1602165138Syongari char *p; 1603165138Syongari register struct top *operandP;/* An operand. Scans all operands. */ 1604165138Syongari /* char c_save; fixme: remove this line *//* What used to live after an expression. */ 1605165138Syongari /* struct frag *fragP; fixme: remove this line *//* Fragment of code we just made. */ 1606165138Syongari /* register struct top *end_operandP; fixme: remove this line *//* -> slot just after last operand 1607165138Syongari Limit of the for (each operand). */ 1608165138Syongari register expressionS *expP; /* -> expression values for this operand */ 1609165138Syongari 1610165138Syongari /* These refer to an instruction operand expression. */ 1611165138Syongari segT to_seg; /* Target segment of the address. */ 1612165138Syongari 1613165138Syongari register valueT this_add_number; 1614165138Syongari register symbolS *this_add_symbol; /* +ve (minuend) symbol. */ 1615165138Syongari 1616165138Syongari /* tahoe_opcodeT opcode_as_number; fixme: remove this line *//* The opcode as a number. */ 1617165138Syongari char *opcodeP; /* Where it is in a frag. */ 1618165138Syongari /* char *opmodeP; fixme: remove this line *//* Where opcode type is, in a frag. */ 1619165138Syongari 1620165138Syongari int dispsize; /* From top_dispsize: tahoe_operand_width 1621165138Syongari (in bytes) */ 1622165138Syongari int is_undefined; /* 1 if operand expression's 1623165138Syongari segment not known yet. */ 1624165138Syongari int pc_rel; /* Is this operand pc relative? */ 1625165138Syongari 1626165138Syongari /* Decode the operand. */ 1627165138Syongari tip (&t, instruction_string); 1628165138Syongari 1629165138Syongari /* 1630165138Syongari * Check to see if this operand decode properly. 1631165138Syongari * Notice that we haven't made any frags yet. 1632165138Syongari * If it goofed, then this instruction will wedge in any pass, 1633165138Syongari * and we can safely flush it, without causing interpass symbol phase 1634165138Syongari * errors. That is, without changing label values in different passes. 1635165138Syongari */ 1636165138Syongari if (*t.tit_error) 1637165138Syongari { 1638165138Syongari as_warn (_("Ignoring statement due to \"%s\""), t.tit_error); 1639165138Syongari } 1640165138Syongari else 1641165138Syongari { 1642165138Syongari /* We saw no errors in any operands - try to make frag(s) */ 1643165138Syongari /* Emit op-code. */ 1644165138Syongari /* Remember where it is, in case we want to modify the op-code later. */ 1645165138Syongari opcodeP = frag_more (1); 1646165138Syongari *opcodeP = t.tit_opcode; 1647165138Syongari /* Now do each operand. */ 1648165138Syongari for (operandP = t.tit_operand; 1649165138Syongari operandP < t.tit_operand + t.tit_operands; 1650165138Syongari operandP++) 1651165138Syongari { /* for each operand */ 1652165138Syongari expP = &(operandP->exp_of_operand); 1653165138Syongari if (operandP->top_ndx >= 0) 1654165138Syongari { 1655165138Syongari /* Indexed addressing byte 1656165138Syongari Legality of indexed mode already checked: it is OK */ 1657165138Syongari FRAG_APPEND_1_CHAR (0x40 + operandP->top_ndx); 1658165138Syongari } /* if(top_ndx>=0) */ 1659165138Syongari 1660165138Syongari /* Here to make main operand frag(s). */ 1661165138Syongari this_add_number = expP->X_add_number; 1662165138Syongari this_add_symbol = expP->X_add_symbol; 1663165138Syongari to_seg = operandP->seg_of_operand; 1664165138Syongari know (to_seg == SEG_UNKNOWN || \ 1665165138Syongari to_seg == SEG_ABSOLUTE || \ 1666165138Syongari to_seg == SEG_DATA || \ 1667165138Syongari to_seg == SEG_TEXT || \ 1668165138Syongari to_seg == SEG_BSS); 1669165138Syongari is_undefined = (to_seg == SEG_UNKNOWN); 1670165138Syongari /* Do we know how big this opperand is? */ 1671165138Syongari dispsize = operandP->top_dispsize; 1672165138Syongari pc_rel = 0; 1673165138Syongari /* Deal with the branch possabilities. (Note, this doesn't include 1674165138Syongari jumps.)*/ 1675165138Syongari if (operandP->top_access == 'b') 1676165138Syongari { 1677165138Syongari /* Branches must be expressions. A psuedo branch can also jump to 1678165138Syongari an absolute address. */ 1679165138Syongari if (to_seg == now_seg || is_undefined) 1680165138Syongari { 1681165138Syongari /* If is_undefined, then it might BECOME now_seg by relax time. */ 1682165138Syongari if (dispsize) 1683165138Syongari { 1684165138Syongari /* I know how big the branch is supposed to be (it's a normal 1685165138Syongari branch), so I set up the frag, and let GAS do the rest. */ 1686165138Syongari p = frag_more (dispsize); 1687165138Syongari fix_new (frag_now, p - frag_now->fr_literal, 1688165138Syongari this_add_symbol, this_add_number, 1689165138Syongari size_to_fx (dispsize, 1), 1690165138Syongari NULL); 1691165138Syongari } 1692165138Syongari else 1693165138Syongari { 1694165138Syongari /* (to_seg==now_seg || to_seg == SEG_UNKNOWN) && dispsize==0 */ 1695165138Syongari /* If we don't know how big it is, then its a synthetic branch, 1696165138Syongari so we set up a simple relax state. */ 1697165138Syongari switch (operandP->top_width) 1698165138Syongari { 1699187325Syongari case TAHOE_WIDTH_CONDITIONAL_JUMP: 1700187325Syongari /* Simple (conditional) jump. I may have to reverse the 1701165138Syongari condition of opcodeP, and then jump to my destination. 1702165138Syongari I set 1 byte aside for the branch off set, and could need 6 1703165138Syongari more bytes for the pc_rel jump */ 1704165138Syongari frag_var (rs_machine_dependent, 7, 1, 1705165138Syongari ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, 1706165138Syongari is_undefined ? STATE_UNDF : STATE_BYTE), 1707165138Syongari this_add_symbol, this_add_number, opcodeP); 1708165138Syongari break; 1709165138Syongari case TAHOE_WIDTH_ALWAYS_JUMP: 1710165138Syongari /* Simple (unconditional) jump. I may have to convert this to 1711165138Syongari a word branch, or an absolute jump. */ 1712165138Syongari frag_var (rs_machine_dependent, 5, 1, 1713165138Syongari ENCODE_RELAX (STATE_ALWAYS_BRANCH, 1714165138Syongari is_undefined ? STATE_UNDF : STATE_BYTE), 1715165138Syongari this_add_symbol, this_add_number, opcodeP); 1716165138Syongari break; 1717165138Syongari /* The smallest size for the next 2 cases is word. */ 1718165138Syongari case TAHOE_WIDTH_BIG_REV_JUMP: 1719165138Syongari frag_var (rs_machine_dependent, 8, 2, 1720165138Syongari ENCODE_RELAX (STATE_BIG_REV_BRANCH, 1721165138Syongari is_undefined ? STATE_UNDF : STATE_WORD), 1722165138Syongari this_add_symbol, this_add_number, 1723165138Syongari opcodeP); 1724165138Syongari break; 1725165138Syongari case TAHOE_WIDTH_BIG_NON_REV_JUMP: 1726165138Syongari frag_var (rs_machine_dependent, 10, 2, 1727165138Syongari ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, 1728165138Syongari is_undefined ? STATE_UNDF : STATE_WORD), 1729165138Syongari this_add_symbol, this_add_number, 1730165138Syongari opcodeP); 1731187325Syongari break; 1732187325Syongari default: 1733165138Syongari as_fatal (_("Compliler bug: Got a case (%d) I wasn't expecting."), 1734165138Syongari operandP->top_width); 1735187325Syongari } 1736187325Syongari } 1737165138Syongari } 1738165138Syongari else 1739165138Syongari { 1740165138Syongari /* to_seg != now_seg && to_seg != seg_unknown (still in branch) 1741165138Syongari In other words, I'm jumping out of my segment so extend the 1742165138Syongari branches to jumps, and let GAS fix them. */ 1743165138Syongari 1744165138Syongari /* These are "branches" what will always be branches around a jump 1745165138Syongari to the correct addresss in real life. 1746165138Syongari If to_seg is SEG_ABSOLUTE, just encode the branch in, 1747165138Syongari else let GAS fix the address. */ 1748165138Syongari 1749165138Syongari switch (operandP->top_width) 1750165138Syongari { 1751165138Syongari /* The theory: 1752165138Syongari For SEG_ABSOLUTE, then mode is ABSOLUTE_ADDR, jump 1753165138Syongari to that addresss (not pc_rel). 1754165138Syongari For other segs, address is a long word PC rel jump. */ 1755165138Syongari case TAHOE_WIDTH_CONDITIONAL_JUMP: 1756165138Syongari /* b<cond> */ 1757165138Syongari /* To reverse the condition in a TAHOE branch, 1758165138Syongari complement bit 4 */ 1759165138Syongari *opcodeP ^= 0x10; 1760165138Syongari p = frag_more (7); 1761165138Syongari *p++ = 6; 1762165138Syongari *p++ = TAHOE_JMP; 1763187325Syongari *p++ = (operandP->top_mode == 1764187325Syongari TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR : 1765165138Syongari TAHOE_PC_REL_LONG); 1766165138Syongari fix_new (frag_now, p - frag_now->fr_literal, 1767165138Syongari this_add_symbol, this_add_number, 1768165138Syongari (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL); 1769165138Syongari /* 1770165138Syongari * Now (eg) BLEQ 1f 1771165138Syongari * JMP foo 1772165138Syongari * 1: 1773165138Syongari */ 1774165138Syongari break; 1775165138Syongari case TAHOE_WIDTH_ALWAYS_JUMP: 1776165138Syongari /* br, just turn it into a jump */ 1777165138Syongari *opcodeP = TAHOE_JMP; 1778165138Syongari p = frag_more (5); 1779165138Syongari *p++ = (operandP->top_mode == 1780165138Syongari TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR : 1781165138Syongari TAHOE_PC_REL_LONG); 1782165138Syongari fix_new (frag_now, p - frag_now->fr_literal, 1783165138Syongari this_add_symbol, this_add_number, 1784165138Syongari (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL); 1785165138Syongari /* Now (eg) JMP foo */ 1786165138Syongari break; 1787165138Syongari case TAHOE_WIDTH_BIG_REV_JUMP: 1788165138Syongari p = frag_more (8); 1789165138Syongari *opcodeP ^= 0x10; 1790165138Syongari *p++ = 0; 1791165138Syongari *p++ = 6; 1792165138Syongari *p++ = TAHOE_JMP; 1793165138Syongari *p++ = (operandP->top_mode == 1794165138Syongari TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR : 1795165138Syongari TAHOE_PC_REL_LONG); 1796165138Syongari fix_new (frag_now, p - frag_now->fr_literal, 1797165138Syongari this_add_symbol, this_add_number, 1798165138Syongari (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL); 1799165138Syongari /* 1800165138Syongari * Now (eg) ACBx 1f 1801165138Syongari * JMP foo 1802165138Syongari * 1: 1803165138Syongari */ 1804165138Syongari break; 1805165138Syongari case TAHOE_WIDTH_BIG_NON_REV_JUMP: 1806165138Syongari p = frag_more (10); 1807165138Syongari *p++ = 0; 1808165138Syongari *p++ = 2; 1809165138Syongari *p++ = TAHOE_BRB; 1810165138Syongari *p++ = 6; 1811165138Syongari *p++ = TAHOE_JMP; 1812165138Syongari *p++ = (operandP->top_mode == 1813165138Syongari TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR : 1814165138Syongari TAHOE_PC_REL_LONG); 1815165138Syongari fix_new (frag_now, p - frag_now->fr_literal, 1816165138Syongari this_add_symbol, this_add_number, 1817165138Syongari (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL); 1818165138Syongari /* 1819165138Syongari * Now (eg) xOBxxx 1f 1820165138Syongari * BRB 2f 1821165138Syongari * 1: JMP @#foo 1822165138Syongari * 2: 1823165138Syongari */ 1824165138Syongari break; 1825165138Syongari case 'b': 1826165138Syongari case 'w': 1827165138Syongari as_warn (_("Real branch displacements must be expressions.")); 1828165138Syongari break; 1829165138Syongari default: 1830165138Syongari as_fatal (_("Complier error: I got an unknown synthetic branch :%c"), 1831165138Syongari operandP->top_width); 1832165138Syongari break; 1833165138Syongari } 1834165138Syongari } 1835165138Syongari } 1836165138Syongari else 1837165138Syongari { 1838165138Syongari /* It ain't a branch operand. */ 1839165138Syongari switch (operandP->top_mode) 1840165138Syongari { 1841165138Syongari /* Auto-foo access, only works for one reg (SP) 1842165138Syongari so the only thing needed is the mode. */ 1843165138Syongari case TAHOE_AUTO_DEC: 1844165138Syongari case TAHOE_AUTO_INC: 1845165138Syongari case TAHOE_AUTO_INC_DEFERRED: 1846165138Syongari FRAG_APPEND_1_CHAR (operandP->top_mode); 1847165138Syongari break; 1848165138Syongari 1849165138Syongari /* Numbered Register only access. Only thing needed is the 1850165138Syongari mode + Register number */ 1851165138Syongari case TAHOE_DIRECT_REG: 1852165138Syongari case TAHOE_REG_DEFERRED: 1853165138Syongari FRAG_APPEND_1_CHAR (operandP->top_mode + operandP->top_reg); 1854165138Syongari break; 1855165138Syongari 1856165138Syongari /* An absolute address. It's size is always 5 bytes. 1857165138Syongari (mode_type + 4 byte address). */ 1858165138Syongari case TAHOE_ABSOLUTE_ADDR: 1859165138Syongari know ((this_add_symbol == NULL)); 1860165138Syongari p = frag_more (5); 1861165138Syongari *p = TAHOE_ABSOLUTE_ADDR; 1862165138Syongari md_number_to_chars (p + 1, this_add_number, 4); 1863165138Syongari break; 1864165138Syongari 1865165138Syongari /* Immediate data. If the size isn't known, then it's an address 1866165138Syongari + and offset, which is 4 bytes big. */ 1867165138Syongari case TAHOE_IMMEDIATE: 1868165138Syongari if (this_add_symbol != NULL) 1869165138Syongari { 1870165138Syongari p = frag_more (5); 1871165138Syongari *p++ = TAHOE_IMMEDIATE_LONGWORD; 1872165138Syongari fix_new (frag_now, p - frag_now->fr_literal, 1873165138Syongari this_add_symbol, this_add_number, 1874165138Syongari FX_32, NULL); 1875165138Syongari } 1876165138Syongari else 1877165138Syongari { 1878165138Syongari /* It's a integer, and I know it's size. */ 1879165138Syongari if ((unsigned) this_add_number < 0x40) 1880165138Syongari { 1881165138Syongari /* Will it fit in a literal? */ 1882165138Syongari FRAG_APPEND_1_CHAR ((byte) this_add_number); 1883165138Syongari } 1884165138Syongari else 1885165138Syongari { 1886165138Syongari p = frag_more (dispsize + 1); 1887165138Syongari switch (dispsize) 1888165138Syongari { 1889165138Syongari case 1: 1890165138Syongari *p++ = TAHOE_IMMEDIATE_BYTE; 1891165138Syongari *p = (byte) this_add_number; 1892165138Syongari break; 1893165138Syongari case 2: 1894165138Syongari *p++ = TAHOE_IMMEDIATE_WORD; 1895165138Syongari md_number_to_chars (p, this_add_number, 2); 1896165138Syongari break; 1897165138Syongari case 4: 1898165138Syongari *p++ = TAHOE_IMMEDIATE_LONGWORD; 1899165138Syongari md_number_to_chars (p, this_add_number, 4); 1900165138Syongari break; 1901165138Syongari } 1902165138Syongari } 1903165138Syongari } 1904165138Syongari break; 1905165138Syongari 1906165138Syongari /* Distance from the PC. If the size isn't known, we have to relax 1907165138Syongari into it. The difference between this and disp(sp) is that 1908165138Syongari this offset is pc_rel, and disp(sp) isn't. 1909165138Syongari Note the drop through code. */ 1910165138Syongari 1911176652Syongari case TAHOE_DISPLACED_RELATIVE: 1912165138Syongari case TAHOE_DISP_REL_DEFERRED: 1913165138Syongari operandP->top_reg = PC_REG; 1914165138Syongari pc_rel = 1; 1915165138Syongari 1916165138Syongari /* Register, plus a displacement mode. Save the register number, 1917165138Syongari and weather its deffered or not, and relax the size if it isn't 1918165138Syongari known. */ 1919165138Syongari case TAHOE_REG_DISP: 1920165138Syongari case TAHOE_REG_DISP_DEFERRED: 1921165138Syongari if (operandP->top_mode == TAHOE_DISP_REL_DEFERRED || 1922165138Syongari operandP->top_mode == TAHOE_REG_DISP_DEFERRED) 1923165138Syongari operandP->top_reg += 0x10; /* deffered mode is always 0x10 higher 1924165138Syongari than it's non-deffered sibling. */ 1925165138Syongari 1926165138Syongari /* Is this a value out of this segment? 1927165138Syongari The first part of this conditional is a cludge to make gas 1928165138Syongari produce the same output as 'as' when there is a lable, in 1929165138Syongari the current segment, displaceing a register. It's strange, 1930165138Syongari and no one in their right mind would do it, but it's easy 1931165138Syongari to cludge. */ 1932165138Syongari if ((dispsize == 0 && !pc_rel) || 1933165138Syongari (to_seg != now_seg && !is_undefined && to_seg != SEG_ABSOLUTE)) 1934165138Syongari dispsize = 4; 1935165138Syongari 1936165138Syongari if (dispsize == 0) 1937165138Syongari { 1938165138Syongari /* 1939165138Syongari * We have a SEG_UNKNOWN symbol, or the size isn't cast. 1940192734Syongari * It might turn out to be in the same segment as 1941192734Syongari * the instruction, permitting relaxation. 1942192734Syongari */ 1943192734Syongari p = frag_var (rs_machine_dependent, 5, 2, 1944165138Syongari ENCODE_RELAX (STATE_PC_RELATIVE, 1945165138Syongari is_undefined ? STATE_UNDF : STATE_BYTE), 1946165138Syongari this_add_symbol, this_add_number, 0); 1947165138Syongari *p = operandP->top_reg; 1948165138Syongari } 1949165138Syongari else 1950165138Syongari { 1951165138Syongari /* Either this is an abs, or a cast. */ 1952165138Syongari p = frag_more (dispsize + 1); 1953165138Syongari switch (dispsize) 1954165138Syongari { 1955165138Syongari case 1: 1956165138Syongari *p = TAHOE_PC_OR_BYTE + operandP->top_reg; 1957165138Syongari break; 1958165138Syongari case 2: 1959165138Syongari *p = TAHOE_PC_OR_WORD + operandP->top_reg; 1960165138Syongari break; 1961165138Syongari case 4: 1962165138Syongari *p = TAHOE_PC_OR_LONG + operandP->top_reg; 1963165138Syongari break; 1964173769Syongari }; 1965173769Syongari fix_new (frag_now, p + 1 - frag_now->fr_literal, 1966165138Syongari this_add_symbol, this_add_number, 1967165138Syongari size_to_fx (dispsize, pc_rel), NULL); 1968165138Syongari } 1969165138Syongari break; 1970165138Syongari default: 1971165138Syongari as_fatal (_("Barf, bad mode %x\n"), operandP->top_mode); 1972165138Syongari } 1973165138Syongari } 1974165138Syongari } /* for(operandP) */ 1975165138Syongari } /* if(!need_pass_2 && !goofed) */ 1976165138Syongari} /* tahoe_assemble() */ 1977165138Syongari 1978165138Syongari 1979165138Syongari/* We have no need to default values of symbols. */ 1980165138Syongari 1981165138Syongari/* ARGSUSED */ 1982165138SyongarisymbolS * 1983165138Syongarimd_undefined_symbol (name) 1984165138Syongari char *name; 1985165138Syongari{ 1986165138Syongari return 0; 1987165138Syongari} /* md_undefined_symbol() */ 1988165138Syongari 1989165138Syongari/* Round up a section size to the appropriate boundary. */ 1990165138SyongarivalueT 1991165138Syongarimd_section_align (segment, size) 1992165138Syongari segT segment; 1993165138Syongari valueT size; 1994165138Syongari{ 1995165138Syongari return ((size + 7) & ~7); /* Round all sects to multiple of 8 */ 1996165138Syongari} /* md_section_align() */ 1997165138Syongari 1998165138Syongari/* Exactly what point is a PC-relative offset relative TO? 1999165138Syongari On the sparc, they're relative to the address of the offset, plus 2000165138Syongari its size. This gets us to the following instruction. 2001165138Syongari (??? Is this right? FIXME-SOON) */ 2002165138Syongarilong 2003165138Syongarimd_pcrel_from (fixP) 2004165138Syongari fixS *fixP; 2005193293Syongari{ 2006193293Syongari return (((fixP->fx_type == FX_8 2007193293Syongari || fixP->fx_type == FX_PCREL8) 2008193293Syongari ? 1 2009193293Syongari : ((fixP->fx_type == FX_16 2010193293Syongari || fixP->fx_type == FX_PCREL16) 2011193293Syongari ? 2 2012193293Syongari : ((fixP->fx_type == FX_32 2013193293Syongari || fixP->fx_type == FX_PCREL32) 2014193293Syongari ? 4 2015193293Syongari : 0))) + fixP->fx_where + fixP->fx_frag->fr_address); 2016193293Syongari} /* md_pcrel_from() */ 2017193293Syongari 2018193293Syongariint 2019193293Syongaritc_is_pcrel (fixP) 2020193293Syongari fixS *fixP; 2021193293Syongari{ 2022193293Syongari /* should never be called */ 2023193293Syongari know (0); 2024193293Syongari return (0); 2025193293Syongari} /* tc_is_pcrel() */ 2026193293Syongari 2027165138Syongari/* end of tc-tahoe.c */ 2028165138Syongari