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