Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    Copyright (c) 1993 Open Software Foundation, Inc.
33
 
34
 
35
    All Rights Reserved
36
 
37
 
38
    Permission to use, copy, modify, and distribute this software
39
    and its documentation for any purpose and without fee is hereby
40
    granted, provided that the above copyright notice appears in all
41
    copies and that both the copyright notice and this permission
42
    notice appear in supporting documentation.
43
 
44
 
45
    OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
46
    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
47
    PARTICULAR PURPOSE.
48
 
49
 
50
    IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
51
    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
52
    LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
53
    NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
54
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
55
*/
56
 
57
/*
58
    		 Crown Copyright (c) 1997
7 7u83 59
 
2 7u83 60
    This TenDRA(r) Computer Program is subject to Copyright
61
    owned by the United Kingdom Secretary of State for Defence
62
    acting through the Defence Evaluation and Research Agency
63
    (DERA).  It is made available to Recipients with a
64
    royalty-free licence for its use, reproduction, transfer
65
    to other parties and amendment for any purpose not excluding
66
    product development provided that any such use et cetera
67
    shall be deemed to be acceptance of the following conditions:-
7 7u83 68
 
2 7u83 69
        (1) Its Recipients shall ensure that this Notice is
70
        reproduced upon any copies or amended versions of it;
7 7u83 71
 
2 7u83 72
        (2) Any amended version of it shall be clearly marked to
73
        show both the nature of and the organisation responsible
74
        for the relevant amendment or amendments;
7 7u83 75
 
2 7u83 76
        (3) Its onward transfer from a recipient to another
77
        party shall be deemed to be that party's acceptance of
78
        these conditions;
7 7u83 79
 
2 7u83 80
        (4) DERA gives no warranty or assurance as to its
81
        quality or suitability for any purpose and DERA accepts
82
        no liability whatsoever in relation to any use to which
83
        it may be put.
84
*/
85
 
86
 
87
 
88
/**********************************************************************
89
$Author: release $
90
$Date: 1998/02/04 15:48:50 $
91
$Revision: 1.2 $
92
$Log: inst_fmt.c,v $
93
 * Revision 1.2  1998/02/04  15:48:50  release
94
 * Added OSF copyright message.
95
 *
96
 * Revision 1.1.1.1  1998/01/17  15:55:57  release
97
 * First version to be checked into rolling release.
98
 *
99
 * Revision 1.2  1996/10/04  16:01:25  pwe
100
 * add banners and mod for PWE ownership
101
 *
102
**********************************************************************/
103
 
104
 
105
/******************************************************************
106
		inst_formats.c
107
 
108
	Procs for outputting various POWER instruction formats to the
109
external file - as_file. Each procedure produces assembler for a family
110
of POWER operations, the actual member is passed as the string
111
understood by the assembler.
112
 
113
******************************************************************/
114
 
115
#include "config.h"
116
#include "geninst.h"
117
 
7 7u83 118
#include "proc.h"
2 7u83 119
#include "myassert.h"
120
#include "flags.h"
121
#include "comment.h"
122
#include "translat.h"
123
#include "maxminmacs.h"		/* for absval() */
124
#include "stack.h"
125
#include "inst_fmt.h"
126
#include "macro.h"
127
#include "mask.h"
7 7u83 128
#define IS_POW2(c)		((c)!= 0 && ((c) & ((c) -1)) == 0)
2 7u83 129
 
7 7u83 130
#define CHECKREG(r)		ASSERT(IS_FIXREG(r) && (!IS_SREG(r) || (r) >= p_sreg_first_save || (r == R_FP)));
2 7u83 131
#define CHECKFREG(r)		ASSERT((!IS_FLT_SREG(r) || (r) >= p_sfreg_first_save));
132
 
133
extern FILE *as_file;
7 7u83 134
char * get_instruction(Instruction_P);
2 7u83 135
 
7 7u83 136
char *ext_name(long id)
2 7u83 137
{
138
  if (id < 0)
139
  {
7 7u83 140
    char *ext = main_globals[(-id) - 1] ->dec_u.dec_val.dec_id;
2 7u83 141
 
142
    return ext;
143
  }
144
  else
145
  {
146
    static char sp[16];
147
 
148
    ASSERT(id > R_LAST);	/* not a confused register */
149
 
150
    sprintf(sp, "L.D%ld", id);
151
    return sp;
152
  }
153
}
154
 
155
/* +++ do better for offset to R_SP too big, trace reg or load extra base reg */
156
 
7 7u83 157
void ld_ro_ins(Instruction_P ins, baseoff a, int dest)
2 7u83 158
{
159
  CHECKREG(dest); CHECKREG(a.base);
160
 
161
  clear_reg(dest);
162
 
163
  if (a.base == R_0)
164
  {
165
    /* base reg of R_0 is not normally allowed, special case 0 offset */
166
    if (a.offset != 0)
167
      fail("ld_ro_ins: non zero offset to R_0");
168
    /* with XXXx (indexed instructions) RA of R_0 is taken as constant 0 */
169
#ifdef DO_ASSEMBLER_MACROS
170
    fprintf(as_file, "\t%sx\t%s,%s,%s",get_instruction(ins),reg_macro(dest),reg_macro(R_0),reg_macro(R_0));
171
#else
172
    fprintf(as_file, "\t%sx\t%d,%d,%d", get_instruction(ins), dest, R_0, R_0);
173
#endif
174
  }
175
  else if (IMM_SIZE(a.offset))
176
  {
177
#ifdef DO_ASSEMBLER_MACROS
178
    fprintf(as_file, "\t%s\t%s,%d(%s)", get_instruction(ins), reg_macro(dest), (int)a.offset, reg_macro(a.base));
179
#else
7 7u83 180
    fprintf(as_file, "\t%s\t%d,%d(%d)", get_instruction(ins), dest,(int)a.offset, a.base);
2 7u83 181
#endif
182
  }
183
  else
184
  {
185
    /* offset too big, put in temp reg and used ld_rr_ins */
186
    /* +++ arrange stack variable to minimise this */
187
    ASSERT(a.base!=R_TMP0);
188
    ld_const_ins(a.offset, R_TMP0);
189
    ld_rr_ins(ins, a.base, R_TMP0, dest);
190
  }
191
}
192
 
193
 
7 7u83 194
void ld_rr_ins(Instruction_P ins, int reg1, int reg2, int dest)
2 7u83 195
{
196
  CHECKREG(dest); CHECKREG(reg1); CHECKREG(reg2);
197
  ASSERT(reg1!=R_0);
198
 
199
  clear_reg(dest);
200
#ifdef DO_ASSEMBLER_MACROS
201
  fprintf(as_file, "\t%sx\t%s,%s,%s\n", get_instruction(ins), reg_macro(dest), reg_macro(reg1), reg_macro(reg2));
202
#else
203
  fprintf(as_file, "\t%sx\t%d,%d,%d\n", get_instruction(ins), dest, reg1, reg2);
204
#endif
205
}
206
 
207
 
7 7u83 208
void set_ins(baseoff a, int dest)
2 7u83 209
{
210
  char *extname = ext_name(a.base);
211
 
212
  CHECKREG(dest);
213
 
214
  clear_reg(dest);
215
#ifdef DO_ASSEMBLER_MACROS
216
  fprintf(as_file, "\t%s\t%s,T.%s(%s)\n", get_instruction(i_l), reg_macro(dest), extname, reg_macro(R_TOC));
217
#else
218
  fprintf(as_file, "\t%s\t%d,T.%s(%d)\n", get_instruction(i_l), dest, extname, R_TOC);
219
#endif
220
  /* +++ offsets in TOC */
221
  if (a.offset != 0)
222
    rir_ins(i_a, dest, a.offset, dest);
223
}
224
 
225
 
7 7u83 226
void ld_ins(Instruction_P ins, baseoff a, int dest)
2 7u83 227
{
228
  /*
229
   * Not a single instruction. Load from baseoff, which may be a global
230
   * requiring a temporary reg.
231
   */
232
 
233
  CHECKREG(dest);
234
 
235
  if (!IS_FIXREG(a.base))
236
  {
237
    /* global */
238
    baseoff tmp_off;
239
 
240
    FULLCOMMENT2("ld_ins ext: off=%#x -> r%d", a.offset, dest);
241
    ASSERT(a.offset==0 || dest!=R_TMP0);
242
 
243
    /* load base into dest reg, then let ld_ro_ins do offset (which may need R_TMP0) */
244
    tmp_off.base = a.base;
245
    tmp_off.offset = 0;
246
 
247
    set_ins(tmp_off, dest);
248
 
249
    tmp_off.base = dest;
250
    tmp_off.offset = a.offset;
251
 
252
    ld_ro_ins(ins, tmp_off, dest);comment(NIL);
253
  }
254
  else
255
  {
256
    ld_ro_ins(ins, a, dest);comment(NIL);
257
  }
258
}
259
 
260
 
7 7u83 261
void st_ro_ins(Instruction_P ins, int src, baseoff a)
2 7u83 262
{
263
  CHECKREG(src); CHECKREG(a.base);
264
 
265
 
266
  /* in general we cannot cope with store using temp reg, catch it always */
267
  if ((src == R_TMP0 || a.base == R_TMP0) && absval(a.offset) > (16 + 1 + 6) * 4)	/* leeway for mem_temp() */
268
    fail("st_ro_ins: store of temp reg to offset not allowed");	/* should not happen */
269
 
270
  if (a.base == R_0)
271
  {
272
    if (a.offset != 0)
273
      fail("st_ro_ins: non zero offset to R_0");
274
    /* with XXXx (indexed instructions) RA of R_0 is taken as constant 0 */
275
#ifdef DO_ASSEMBLER_MACROS
276
    fprintf(as_file, "\t%sx\t%s,%s,%s", get_instruction(ins), reg_macro(src), reg_macro(R_0), reg_macro(R_0));
277
#else
278
    fprintf(as_file, "\t%sx\t%d,%d,%d", get_instruction(ins), src, R_0, R_0);
279
#endif
280
  }
281
  else if (IMM_SIZE(a.offset))
282
  {
283
#ifdef DO_ASSEMBLER_MACROS
284
    fprintf(as_file, "\t%s\t%s,%d(%s)", get_instruction(ins), reg_macro(src), (int)a.offset, reg_macro(a.base));
285
#else
7 7u83 286
    fprintf(as_file, "\t%s\t%d,%d(%d)", get_instruction(ins), src,(int)a.offset, a.base);
2 7u83 287
#endif
288
  }
289
  else
290
  {
291
    /* offset too big, put in temp reg and used st_rr_ins */
292
    /* +++ arrange stack variable to minimise this */
293
    COMMENT("st_ro_ins: big offset, use temp reg and st_rr_ins");
294
    ASSERT(a.base!=R_TMP0);		/* otherwise we corrupt it */
295
    ld_const_ins(a.offset, R_TMP0);
296
    st_rr_ins(ins, src, a.base, R_TMP0);
297
  }
298
}
299
 
300
 
7 7u83 301
void st_rr_ins(Instruction_P ins, int src, int reg1, int reg2)
2 7u83 302
{
303
  CHECKREG(src); CHECKREG(reg1); CHECKREG(reg2);
304
  ASSERT(reg1!=R_0);
305
#ifdef DO_ASSEMBLER_MACROS
306
  fprintf(as_file, "\t%sx\t%s,%s,%s\n", get_instruction(ins), reg_macro(src), reg_macro(reg1), reg_macro(reg2));
307
#else
308
  fprintf(as_file, "\t%sx\t%d,%d,%d\n", get_instruction(ins), src, reg1, reg2);
309
#endif
310
}
311
 
312
 
7 7u83 313
void st_ins(Instruction_P ins, int src, baseoff a)
2 7u83 314
{
315
  /*
316
   * Not a single instruction. Store into baseoff, which may be a global
317
   * requiring a temporary reg.
318
   */
319
 
320
  CHECKREG(src);
321
 
322
  if (!IS_FIXREG(a.base))
323
  {
324
    /* global */
325
    baseoff tmp_off;
326
 
327
    if (src == R_TMP0)
328
      fail("st_ins: store of temp reg to global not allowed");	/* should not happen */
329
 
330
    tmp_off.base = R_TMP0;
331
    tmp_off.offset = 0;
332
 
333
    set_ins(a, R_TMP0);
334
    st_ro_ins(ins, src, tmp_off);comment(NIL);
335
  }
336
  else
337
  {
338
    st_ro_ins(ins, src, a);comment(NIL);
339
  }
340
}
341
 
342
 
343
/* 3 register operand instructions, source1, source2, destination */
7 7u83 344
void rrr_ins(Instruction_P ins, int src1, int src2, int dest)
2 7u83 345
{
346
  CHECKREG(dest); CHECKREG(src1); CHECKREG(src2);
347
 
348
  clear_reg(dest);
349
 
350
  /* i_s is a pseudo instruction, use i_sf with reversed ops */
351
  if (ins == i_s)
352
  {
353
#ifdef DO_ASSEMBLER_MACROS
354
    fprintf(as_file, "\t%s\t%s,%s,%s\n", get_instruction(i_sf), reg_macro(dest), reg_macro(src2), reg_macro(src1));
355
#else
356
    fprintf(as_file, "\t%s\t%d,%d,%d\n", get_instruction(i_sf), dest, src2, src1);
357
#endif
358
  }
359
  else
360
  {
361
#ifdef DO_ASSEMBLER_MACROS
362
    fprintf(as_file, "\t%s\t%s,%s,%s\n", get_instruction(ins), reg_macro(dest), reg_macro(src1), reg_macro(src2));
363
#else
364
    fprintf(as_file, "\t%s\t%d,%d,%d\n", get_instruction(ins), dest, src1, src2);
365
#endif
366
  }
7 7u83 367
 
2 7u83 368
}
369
 
370
 
371
/* source register, immediate, destination register instructions */
372
 
7 7u83 373
void rir_ins(Instruction_P ins, int src, long imm, int dest)
2 7u83 374
{
7 7u83 375
  bool logical = ins == i_and || ins == i_or || ins == i_xor||
2 7u83 376
    ins ==i_and_cr|| ins==i_or_cr || ins==i_xor_cr;
377
 
378
  CHECKREG(dest); CHECKREG(src);
379
  ASSERT(ins!=i_divs&&ins!=i_div);	/* no divi, so we should not be called for div */
380
 
381
  /*
382
   * Check agaonst IBM assembler bug which we should avoid at higher levels:
383
   * IX25505 bosadt : SRI 30,29,0 DOES NOT ASSEMBLE CORRECTLY
384
   */
385
  ASSERT(!(ins==i_sr && imm==0));
386
 
387
  clear_reg(dest);
388
 
389
  if (!logical && IMM_SIZE(imm))
390
  {
391
    Instruction_P imins;
7 7u83 392
    if     (ins==i_a)      imins=i_ai;
393
    else if (ins==i_a_cr)   imins=i_ai_cr;
394
    else if (ins==i_sf)     imins=i_sfi;
395
    else if (ins==i_sl)     imins=i_sli;
396
    else if (ins==i_sl_cr)  imins=i_sli_cr;
397
    else if (ins==i_sr)     imins=i_sri;
398
    else if (ins==i_sr_cr)  imins=i_sri_cr;
399
    else if (ins==i_sra)    imins=i_srai;
400
    else if (ins==i_sra_cr) imins=i_srai_cr;
401
    else if (ins==i_muls)   imins=i_muli;
2 7u83 402
    else
403
    {
404
      printf("Unknown immediate instruction for %s\n",get_instruction(ins));
7 7u83 405
      imins=ins;
2 7u83 406
    }
7 7u83 407
 
408
#ifdef DO_ASSEMBLER_MACROS
2 7u83 409
    fprintf(as_file,"\t%s\t%s,%s,%ld\n",get_instruction(imins), reg_macro(dest), reg_macro(src), imm);
410
#else
411
    fprintf(as_file,"\t%s\t%d,%d,%ld\n",get_instruction(imins), dest, src, imm);
412
#endif
413
 
414
    return;
415
  }
416
 
417
  if (ins == i_a && IMMLOGU_SIZE(imm))
418
  {
419
    unsigned long uimm = imm;
420
#ifdef DO_ASSEMBLER_MACROS
421
    fprintf(as_file, "\t%s\t%s,%s,%ld\n", get_instruction(i_cau), reg_macro(dest), reg_macro(src), uimm >> 16);
422
#else
423
    fprintf(as_file, "\t%s\t%d,%d,%ld\n", get_instruction(i_cau), dest, src, uimm >> 16);
424
#endif
425
    return;
426
  }
427
 
7 7u83 428
  if ((ins == i_a || ins == i_s) && IMM_SIZE((imm/2) +1) && dest != R_SP)
2 7u83 429
  {
430
    COMMENT1("rir_ins: special casing add/sub of constant %ld", imm);
431
    if (ins == i_s && imm == 0x8000)
432
    {
433
      /* use -0x8000 as imm, which is immediate */
434
      rir_ins(i_a, src, -imm, dest);
435
    }
436
    else
437
    {
438
      /* use 2 adds or subs */
439
      long half = imm / 2;
440
 
441
      rir_ins(ins, src, half, dest);
442
      rir_ins(ins, dest, imm - half, dest);
443
    }
444
    return;
445
  }
446
 
447
  if (ins == i_and)
448
  {
449
    /*
450
     * See if we can use rlinm instruction, ie a single series of one bits.
451
     * This is prefered to generating an andiX. below, which may cause
452
     * a CR delay.
453
     */
454
    unsigned long x = imm;
455
 
456
    ASSERT(x != 0);		/* should be handled above */
457
    if (is_a_mask(x) || is_a_mask(~x))
458
    {
459
      COMMENT1("rir_ins: special casing and of constant %#lx", imm);
460
#ifdef DO_ASSEMBLER_MACROS
461
      fprintf(as_file, "\t%s\t%s,%s,0,0x%lx\n", get_instruction(i_rlinm), reg_macro(dest), reg_macro(src), imm);
462
#else
463
      fprintf(as_file, "\t%s\t%d,%d,0,0x%lx\n", get_instruction(i_rlinm), dest, src, imm);
464
#endif
465
      return;
466
    }
467
  }
468
  if (ins == i_and_cr)
469
  {
470
    /*
471
     * See if we can use rlinm instruction, ie a single series of one bits.
472
     * This is prefered to generating an andiX. below, which may cause
473
     * a CR delay.
474
     */
475
    unsigned long x = imm;
476
 
477
    ASSERT(x != 0);		/* should be handled above */
478
    if (is_a_mask(x) || is_a_mask(~x))
479
    {
480
      COMMENT1("rir_ins: special casing and of constant %#lx", imm);
481
#ifdef DO_ASSEMBLER_MACROS
482
      fprintf(as_file, "\t%s\t%s,%s,0,0x%lx\n", get_instruction(i_rlinm_cr), reg_macro(dest), reg_macro(src), imm);
483
#else
484
      fprintf(as_file, "\t%s\t%d,%d,0,0x%lx\n", get_instruction(i_rlinm_cr), dest, src, imm);
485
#endif
486
      return;
487
    }
488
  }
489
 
7 7u83 490
 
2 7u83 491
  if (logical && IMMLOGL_SIZE(imm))  /* Lower 16 bit load */
492
  {
493
    Instruction_P ilins;
7 7u83 494
    if     (ins==i_and) ilins = i_andil_cr;
495
    else if (ins==i_or)  ilins = i_oril;
496
    else if (ins==i_xor) ilins = i_xoril;
497
    else if (ins==i_and_cr)ilins = i_andil_cr;
2 7u83 498
    else fail("Should never reach here");
499
#ifdef DO_ASSEMBLER_MACROS
500
    fprintf(as_file, "\t%s\t%s,%s,%ld\n", get_instruction(ilins), reg_macro(dest), reg_macro(src), imm);
501
#else
502
    fprintf(as_file, "\t%s\t%d,%d,%ld\n", get_instruction(ilins), dest, src, imm);
503
#endif
504
    return;
505
  }
506
 
7 7u83 507
  if (logical && IMMLOGU_SIZE(imm))  /* Upper 16 bit load */
2 7u83 508
  {
509
    unsigned long uimm = imm;
510
    Instruction_P iuins;
7 7u83 511
    if     (ins==i_and) iuins = i_andiu_cr;
512
    else if (ins==i_or)  iuins = i_oriu;
513
    else if (ins==i_xor) iuins = i_xoriu;
514
    else if (ins==i_and_cr)iuins = i_andiu_cr;
2 7u83 515
    else fail("Should never reach here");
516
#ifdef DO_ASSEMBLER_MACROS
517
    fprintf(as_file, "\t%s\t%s,%s,%ld\n",get_instruction(iuins), reg_macro(dest), reg_macro(src), uimm >> 16);
518
#else
519
    fprintf(as_file, "\t%s\t%d,%d,%ld\n",get_instruction(iuins), dest, src, uimm >> 16);
520
#endif
521
    return;
522
  }
523
 
524
  if (ins == i_or)
525
  {
526
    /* or lower and then upper end */
527
    unsigned long uimm = imm;
528
#ifdef DO_ASSEMBLER_MACROS
529
    fprintf(as_file, "\t%s\t%s,%s,0x%lx\n", get_instruction(i_oril), reg_macro(dest), reg_macro(src), uimm & 0xffff);
530
    fprintf(as_file, "\t%s\t%s,%s,0x%lx\n", get_instruction(i_oriu), reg_macro(dest), reg_macro(dest), uimm >> 16);
531
#else
532
    fprintf(as_file, "\t%s\t%d,%d,0x%lx\n", get_instruction(i_oril), dest, src, uimm & 0xffff);
533
    fprintf(as_file, "\t%s\t%d,%d,0x%lx\n", get_instruction(i_oriu), dest, dest, uimm >> 16);
534
#endif
535
 
536
    return;
537
  }
538
 
539
  /* default: use temp reg for large constant */
540
  COMMENT("rir_ins: large constant in R_TMP0");
541
  if (src == R_TMP0)
542
    fail("rir_ins: temp reg in use when needed for large constant");	/* should not happen */
543
  ld_const_ins(imm, R_TMP0);
544
  rrr_ins(ins, src, R_TMP0, dest);
545
}
546
 
547
/* register to register pseudo instruction */
7 7u83 548
void rr_ins(Instruction_P ins, int src, int dest)
2 7u83 549
{
550
  CHECKREG(dest); CHECKREG(src);
551
 
552
  clear_reg(dest);
553
  if (ins == i_not)
554
    rir_ins(i_sf, src, -1, dest);		/* implements monadic not */
555
  else
556
#ifdef DO_ASSEMBLER_MACROS
557
    fprintf(as_file, "\t%s\t%s,%s\n", get_instruction(ins), reg_macro(dest), reg_macro(src));
558
#else
559
    fprintf(as_file, "\t%s\t%d,%d\n", get_instruction(ins), dest, src);
560
#endif
561
}
562
 
563
 
564
 
565
/* mov fixed point reg to another */
7 7u83 566
void mov_rr_ins(int src, int dest)
2 7u83 567
{
568
  CHECKREG(dest); CHECKREG(src);
569
 
570
  if (src != dest)
571
  {
572
    clear_reg(dest);
573
    /* move by i_oril of src with 0 to dest */
574
#ifdef DO_ASSEMBLER_MACROS
575
    fprintf(as_file, "\t%s\t%s,%s,%d", get_instruction(i_oril), reg_macro(dest), reg_macro(src), 0);
576
#else
577
    fprintf(as_file, "\t%s\t%d,%d,%d", get_instruction(i_oril), dest, src, 0);
578
#endif
579
  }
580
}
581
 
582
 
583
/* load const into fixed point reg */
7 7u83 584
void ld_const_ins(long imm, int dest)
2 7u83 585
{
586
  CHECKREG(dest);
587
 
588
  clear_reg(dest);
589
 
590
  if (IMM_SIZE(imm))
591
  {
592
#ifdef DO_ASSEMBLER_MACROS
593
    fprintf(as_file, "\t%s\t%s,%ld\n", get_instruction(i_lil), reg_macro(dest), imm);
594
#else
595
    fprintf(as_file, "\t%s\t%d,%ld\n", get_instruction(i_lil), dest, imm);
596
#endif
597
  }
598
  else
599
  {
600
    unsigned long uimm = imm;
601
    unsigned long uimml = uimm & 0xffff;
602
 
603
    /* load upper 16 bits */
604
#ifdef DO_ASSEMBLER_MACROS
605
    fprintf(as_file, "\t%s\t%s,0x%lx\n",get_instruction(i_liu), reg_macro(dest), uimm >> 16);
606
#else
607
    fprintf(as_file, "\t%s\t%d,0x%lx\n",get_instruction(i_liu), dest, uimm >> 16);
608
#endif
609
    /* or in lower 16 bits if needed */
610
    if (uimml != 0)
611
    {
612
#ifdef DO_ASSEMBLER_MACROS
613
      fprintf(as_file, "\t%s\t%s,%s,0x%lx\n", get_instruction(i_oril), reg_macro(dest), reg_macro(dest), uimml);
614
#else
615
      fprintf(as_file, "\t%s\t%d,%d,0x%lx\n", get_instruction(i_oril), dest, dest, uimml);
616
#endif
617
    }
618
  }
619
}
620
 
621
 
622
/* move from branch unit to fixed point reg */
7 7u83 623
void mf_ins(Instruction_P ins, int dest)
2 7u83 624
{
625
  if (ins !=i_mffs)
626
  {
627
    CHECKREG(dest);
628
    clear_reg(dest);
629
  }
7 7u83 630
  else
2 7u83 631
  {
632
    CHECKFREG(dest);
633
    clear_freg(dest);
634
  }
635
#ifdef DO_ASSEMBLER_MACROS
636
  fprintf(as_file, "\t%s\t%s\n", get_instruction(ins), reg_macro(dest));
637
#else
638
  fprintf(as_file, "\t%s\t%d\n", get_instruction(ins), dest);
639
#endif
640
}
641
 
642
/* move to branch unit from fixed point reg */
7 7u83 643
void mt_ins(Instruction_P ins, int src)
2 7u83 644
{
645
  CHECKREG(src);
646
#ifdef DO_ASSEMBLER_MACROS
647
  fprintf(as_file, "\t%s\t%s\n", get_instruction(ins), reg_macro(src));
648
#else
649
  fprintf(as_file, "\t%s\t%d\n", get_instruction(ins), src);
650
#endif
651
}
652
 
653
 
654
 
655
/* zeroadic pseudo instruction */
7 7u83 656
void z_ins(Instruction_P ins)
2 7u83 657
{
658
  fprintf(as_file, "\t%s\n", get_instruction(ins));
659
}
660
 
661
 
662
/******************************************************************************
663
Branch instructions. These have labels as destination.
664
******************************************************************************/
665
 
666
/* unconditional branch */
7 7u83 667
void uncond_ins(Instruction_P ins, int lab)
2 7u83 668
{
669
  fprintf(as_file, "\t%s\tL.%d\n", get_instruction(ins), lab);
670
}
671
 
672
 
673
 
674
 
675
/*
676
 * Call, and external jump instructions.
677
 */
678
 
679
/* jump/call to external identifier */
7 7u83 680
void extj_ins(Instruction_P ins, baseoff b)
2 7u83 681
{
682
  char *ext;
683
 
7 7u83 684
  FULLCOMMENT1("extj_ins: global proc no=%d",(-b.base) - 1);
685
  ASSERT(((-b.base) -1) >=0);
2 7u83 686
 
7 7u83 687
  ext = main_globals[(-b.base) - 1] ->dec_u.dec_val.dec_id;
2 7u83 688
 
689
  fprintf(as_file, "\t%s\t.%s\n", get_instruction(ins), ext);
690
 
691
  /*
692
   * By convention a special no-op is generated after a call,
693
   * which the linker changes to reload our TOC reg (2) if the
694
   * call is inter-module.
695
   *
696
   * We optimise by omitting the no-op where we know the call is intra-module.
697
   */
7 7u83 698
  if (diagnose || !main_globals[(-b.base) -1] ->dec_u.dec_val.have_def)
2 7u83 699
  {
700
    fprintf(as_file, "\t%s\t%d,%d,%d\n", get_instruction(i_cror), 15, 15, 15);	/* conventional nop */
701
  }
7 7u83 702
 
2 7u83 703
}
704
 
705
/* jump/call to compiler generated external identifier, eg .mul */
7 7u83 706
void extj_special_ins(Instruction_P ins, char *nm)
2 7u83 707
{
708
  fprintf(as_file, "\t%s\t%s\n", get_instruction(ins), nm);
709
  fprintf(as_file, "\t%s\t%d,%d,%d\n", get_instruction(i_cror), 15, 15, 15);	/* conventional nop */
710
}
711
 
712
 
713
/*
714
 * Conditional instructions.
715
 */
716
 
717
/* branch conditional instruction */
7 7u83 718
void bc_ins(Instruction_P ins, int creg, int lab, int prediction)
2 7u83 719
{
7 7u83 720
  if (architecture == POWERPC_CODE)
2 7u83 721
  {
7 7u83 722
 
2 7u83 723
    int BI;
724
    int BO;
725
    BI=creg*4;
7 7u83 726
 
2 7u83 727
    if (ins==i_ble)
728
    {
729
      BO  = 4;
730
      BI += 1;
731
    }
732
    else if (ins ==i_blt)
733
    {
734
      BO  = 12;
735
      BI += 0;
736
    }
737
    else if (ins == i_bge)
738
    {
7 7u83 739
      BO  = 4;
2 7u83 740
      BI += 0;
7 7u83 741
    }
2 7u83 742
    else if (ins == i_bgt)
743
    {
744
      BO  = 12;
745
      BI += 1;
746
    }
7 7u83 747
    else if (ins == i_bne)
2 7u83 748
    {
749
      BO  = 4;
750
      BI += 2;
751
    }
752
    else if (ins == i_beq)
753
    {
754
      BO  = 12;
755
      BI += 2;
756
    }
7 7u83 757
    else
2 7u83 758
    {
759
      fprintf(as_file,"\t%s\t%d,L.%d\n",get_instruction(ins),creg,lab);
760
      return;
761
    }
7 7u83 762
    if (prediction)
2 7u83 763
    {
764
      BO+=1;
765
    }
766
    fprintf(as_file,"\t%s\t%d,%d,L.%d\n",get_instruction(i_bc),BO,BI,lab);
767
  }
768
  else
769
  {
770
#ifdef DO_ASSEMBLER_MACROS
771
    fprintf(as_file,"\t%s\t%s,L.%d\n",get_instruction(ins),cr_macro(creg),lab);
772
#else
773
    fprintf(as_file,"\t%s\t%d,L.%d\n",get_instruction(ins),creg,lab);
774
#endif
775
  }
776
}
777
/* branch conditional instruction */
7 7u83 778
void long_bc_ins(Instruction_P ins, int creg, int lab, int prediction)
2 7u83 779
{
780
  /* same as bc_ins only the test is reversed so that the lab is called directly so that there is no chance of the branch being out of range */
781
 
782
  long new_lab = lab;
783
  lab = new_label();
7 7u83 784
  if     (ins==i_blt) {ins = i_bge;}
785
  else if (ins==i_ble) {ins = i_bgt;}
786
  else if (ins==i_bne) {ins = i_beq;}
787
  else if (ins==i_beq) {ins = i_bne;}
788
  else if (ins==i_bgt) {ins = i_ble;}
789
  else if (ins==i_bge) {ins = i_blt;}
790
  else if (ins==i_bso) {ins = i_bns;}
791
  else if (ins==i_bns) {ins = i_bso;}
2 7u83 792
  else
793
  {
794
    fail("Don't know how to reverse this test");
795
  }
7 7u83 796
 
797
  if (architecture == POWERPC_CODE)
2 7u83 798
  {
7 7u83 799
 
2 7u83 800
    int BI;
801
    int BO;
802
    BI=creg*4;
7 7u83 803
 
2 7u83 804
    if (ins==i_ble)
805
    {
806
      BO  = 4;
807
      BI += 1;
808
    }
809
    else if (ins ==i_blt)
810
    {
811
      BO  = 12;
812
      BI += 0;
813
    }
814
    else if (ins == i_bge)
815
    {
7 7u83 816
      BO  = 4;
2 7u83 817
      BI += 0;
7 7u83 818
    }
2 7u83 819
    else if (ins == i_bgt)
820
    {
821
      BO  = 12;
822
      BI += 1;
823
    }
7 7u83 824
    else if (ins == i_bne)
2 7u83 825
    {
826
      BO  = 4;
827
      BI += 2;
828
    }
829
    else if (ins == i_beq)
830
    {
831
      BO  = 12;
832
      BI += 2;
833
    }
7 7u83 834
    else
2 7u83 835
    {
836
      fprintf(as_file,"\t%s\t%d,L.%d\n",get_instruction(ins),creg,lab);
837
      uncond_ins(i_b,new_lab);
838
      set_label(lab);
839
      return;
840
    }
7 7u83 841
    if (prediction)
2 7u83 842
    {
843
      BO+=1;
844
    }
845
    fprintf(as_file,"\t%s\t%d,%d,L.%d\n",get_instruction(i_bc),BO,BI,lab);
846
    uncond_ins(i_b,new_lab);
847
    set_label(lab);
848
    return;
849
  }
850
  else
851
  {
852
#ifdef DO_ASSEMBLER_MACROS
853
    fprintf(as_file,"\t%s\t%s,L.%d\n",get_instruction(ins),cr_macro(creg),lab);
854
#else
855
    fprintf(as_file,"\t%s\t%d,L.%d\n",get_instruction(ins),creg,lab);
856
 
857
#endif
858
    uncond_ins(i_b,new_lab);
859
    set_label(lab);
860
    return;
861
  }
862
}
863
 
864
 
865
/* cmp or cmpl instruction */
7 7u83 866
void cmp_rr_ins(Instruction_P ins, int reg1, int reg2, int cr_dest)
2 7u83 867
{
868
  CHECKREG(reg1); CHECKREG(reg2);
869
#ifdef DO_ASSEMBLER_MACROS
870
  fprintf(as_file, "\t%s\t%s,%s,%s\n", get_instruction(ins), cr_macro(cr_dest), reg_macro(reg1), reg_macro(reg2));
871
#else
872
  fprintf(as_file, "\t%s\t%d,%d,%d\n", get_instruction(ins), cr_dest, reg1, reg2);
873
#endif
874
}
875
 
876
 
877
/* for cmpi or cmpli instruction */
7 7u83 878
void cmp_ri_ins(Instruction_P ins, int reg, long imm, int cr_dest)
2 7u83 879
{
880
  CHECKREG(reg);
881
 
882
  /* +++ for equality can use cmpi or cmpli for larger constant range */
883
  if (ins == i_cmp && IMM_SIZE(imm))
884
  {
885
#ifdef DO_ASSEMBLER_MACROS
886
    fprintf(as_file, "\t%si\t%s,%s,%ld\n", get_instruction(ins), cr_macro(cr_dest), reg_macro(reg), imm);
887
#else
888
    fprintf(as_file, "\t%si\t%d,%d,%ld\n", get_instruction(ins), cr_dest, reg, imm);
889
#endif
890
  }
891
  else if (ins == i_cmpl && IMMLOGL_SIZE(imm))
892
  {
893
#ifdef DO_ASSEMBLER_MACROS
894
    fprintf(as_file, "\t%si\t%s,%s,%ld\n", get_instruction(ins), cr_macro(cr_dest), reg_macro(reg), imm);
895
#else
896
    fprintf(as_file, "\t%si\t%d,%d,%ld\n", get_instruction(ins), cr_dest, reg, imm);
897
#endif
898
  }
899
  else
900
  {
901
    /* use temp reg for large constant */
902
    COMMENT("condri_ins: large constant in R_TMP0");
903
    if (reg == R_TMP0)
904
      fail("cmp_ri_ins: temp reg in use when needed for large constant");	/* should not happen */
905
    ld_const_ins(imm, R_TMP0);
906
    cmp_rr_ins(ins, reg, R_TMP0, cr_dest);
907
  }
908
}
909
 
910
 
911
 
912
 
913
/*
914
 * Floating point instructions.
915
 */
916
 
7 7u83 917
void ldf_ro_ins(Instruction_P ins, baseoff a, int dest)
2 7u83 918
{
919
  CHECKREG(a.base); CHECKFREG(dest);
920
 
921
  clear_freg(dest);
922
 
923
  if (a.base == R_0)
924
  {
925
    if (a.offset != 0)
926
      fail("ldf_ro_ins: non zero offset to R_0");
927
    /* with XXXx (indexed instructions) RA of R_0 is taken as constant 0 */
928
#ifdef DO_ASSEMBLER_MACROS
929
    fprintf(as_file, "\t%sx\t%s,%s,%s\n", get_instruction(ins), freg_macro(dest), reg_macro(R_0), reg_macro(R_0));
930
#else
931
    fprintf(as_file, "\t%sx\t%d,%d,%d\n", get_instruction(ins), dest, R_0, R_0);
932
#endif
933
  }
934
  else
935
  if (IMM_SIZE(a.offset))
936
  {
937
#ifdef DO_ASSEMBLER_MACROS
938
    fprintf(as_file, "\t%s\t%s,%d(%s)\n", get_instruction(ins), freg_macro(dest), (int)a.offset, reg_macro(a.base));
939
#else
7 7u83 940
    fprintf(as_file, "\t%s\t%d,%d(%d)\n", get_instruction(ins), dest,(int)a.offset, a.base);
2 7u83 941
#endif
942
  }
943
  else
944
  {
945
    /* offset too big, put in temp reg and used ld_rr_ins */
946
    /* +++ arrange stack variable to minimise this */
947
    COMMENT("ldf_ro_ins: big offset, use R_TMP0 and ldf_rr_ins");
948
    ASSERT(a.base!=R_TMP0);		/* otherwise we corrupt it */
949
    ld_const_ins(a.offset, R_TMP0);
950
    ldf_rr_ins(ins, a.base, R_TMP0, dest);
951
  }
952
}
953
 
954
 
7 7u83 955
void ldf_rr_ins(Instruction_P ins, int reg1, int reg2, int dest)
2 7u83 956
{
957
  CHECKREG(reg1); CHECKREG(reg2); CHECKFREG(dest);
958
 
959
  clear_freg(dest);
960
#ifdef DO_ASSEMBLER_MACROS
961
  fprintf(as_file, "\t%sx\t%s,%s,%s\n", get_instruction(ins), freg_macro(dest), reg_macro(reg1), reg_macro(reg2));
962
#else
963
  fprintf(as_file, "\t%sx\t%d,%d,%d\n", get_instruction(ins), dest, reg1, reg2);
964
#endif
965
}
966
 
967
 
7 7u83 968
void ldf_ins(Instruction_P ins, baseoff a, int dest)
2 7u83 969
{
970
  /*
971
   * Not a single instruction. Load from baseoff, which may be a global
972
   * requiring a temporary reg.
973
   */
974
 
975
  CHECKFREG(dest);
976
 
977
  if (!IS_FIXREG(a.base))
978
  {
979
    /* global */
980
    baseoff tmp_off;
981
 
982
    tmp_off.base = R_TMP0;
983
    tmp_off.offset = 0;
984
 
985
    set_ins(a, R_TMP0);
986
    ldf_ro_ins(ins, tmp_off, dest);
987
  }
988
  else
989
  {
990
    ldf_ro_ins(ins, a, dest);
991
  }
992
}
993
 
994
 
7 7u83 995
void stf_ro_ins(Instruction_P ins, int src, baseoff a)
2 7u83 996
{
997
  CHECKREG(a.base); CHECKFREG(src);
998
 
999
  /* in general we cannot cope with store using temp reg, catch it always */
1000
  if (a.base == R_TMP0 && absval(a.offset) > (16 + 1 + 6) * 4)	/* leeway for mem_temp() */
1001
    fail("stf_ro_ins: store of temp reg to offset not allowed");	/* should not happen */
1002
 
1003
  if (a.base == R_0)
1004
  {
1005
    if (a.offset != 0)
1006
      fail("stf_ro_ins: non zero offset to R_0");
1007
    /* with XXXx (indexed instructions) RA of R_0 is taken as constant 0 */
1008
#ifdef DO_ASSEMBLER_MACROS
1009
    fprintf(as_file, "\t%sx\t%s,%s,%s\n", get_instruction(ins), freg_macro(src), reg_macro(R_0), reg_macro(R_0));
1010
#else
1011
    fprintf(as_file, "\t%sx\t%d,%d,%d\n", get_instruction(ins), src, R_0, R_0);
1012
#endif
1013
  }
1014
  else
1015
  if (IMM_SIZE(a.offset))
1016
  {
1017
#ifdef DO_ASSEMBLER_MACROS
1018
    fprintf(as_file, "\t%s\t%s,%d(%s)\n", get_instruction(ins), freg_macro(src), (int)a.offset, reg_macro(a.base));
1019
#else
7 7u83 1020
    fprintf(as_file, "\t%s\t%d,%d(%d)\n", get_instruction(ins), src,(int)a.offset, a.base);
2 7u83 1021
#endif
1022
  }
1023
  else
1024
  {
1025
    /* offset too big, put in temp reg and used stf_rr_ins */
1026
    /* +++ arrange stack variable to minimise this */
1027
    COMMENT("stf_ro_ins: big offset, use temp reg and stf_rr_ins");
1028
    ASSERT(a.base!=R_TMP0);		/* otherwise we corrupt it */
1029
    ld_const_ins(a.offset, R_TMP0);
1030
    stf_rr_ins(ins, src, a.base, R_TMP0);
1031
  }
1032
}
1033
 
1034
 
7 7u83 1035
void stf_rr_ins(Instruction_P ins, int src, int reg1, int reg2)
2 7u83 1036
{
1037
  CHECKREG(reg1); CHECKREG(reg2);
1038
#ifdef DO_ASSEMBLER_MACROS
1039
  fprintf(as_file, "\t%sx\t%s,%s,%s\n", get_instruction(ins), freg_macro(src), reg_macro(reg1), reg_macro(reg2));
1040
#else
1041
  fprintf(as_file, "\t%sx\t%d,%d,%d\n", get_instruction(ins), src, reg1, reg2);
1042
#endif
1043
}
1044
 
1045
 
7 7u83 1046
void stf_ins(Instruction_P ins, int src, baseoff a)
2 7u83 1047
{
1048
  /*
1049
   * Not a single instruction. Store into baseoff, which may be a global
1050
   * requiring a temporary reg.
1051
   */
1052
 
1053
  CHECKFREG(src);
1054
 
1055
  if (!IS_FIXREG(a.base))
1056
  {
1057
    /* global */
1058
    baseoff tmp_off;
1059
 
1060
    tmp_off.base = R_TMP0;
1061
    tmp_off.offset = 0;
1062
 
1063
    set_ins(a, R_TMP0);
1064
    stf_ro_ins(ins, src, tmp_off);
1065
  }
1066
  else
1067
  {
1068
    stf_ro_ins(ins, src, a);
1069
  }
1070
}
1071
 
1072
 
7 7u83 1073
void rrf_cmp_ins(Instruction_P ins, int reg1, int reg2, int cr_dest)
2 7u83 1074
{
1075
  CHECKFREG(reg1); CHECKFREG(reg2);
1076
#ifdef DO_ASSEMBLER_MACROS
1077
  fprintf(as_file, "\t%s\t%s,%s,%s\n", get_instruction(ins), cr_macro(cr_dest), freg_macro(reg1), freg_macro(reg2));
1078
#else
1079
  fprintf(as_file, "\t%s\t%d,%d,%d\n", get_instruction(ins), cr_dest, reg1, reg2);
1080
#endif
1081
}
1082
 
1083
 
7 7u83 1084
void rrf_ins(Instruction_P ins, int src, int dest)
2 7u83 1085
{
1086
  CHECKFREG(dest); CHECKFREG(src);
1087
 
1088
  clear_freg(dest);
1089
#ifdef DO_ASSEMBLER_MACROS
1090
  fprintf(as_file, "\t%s\t%s,%s\n", get_instruction(ins), freg_macro(dest), freg_macro(src));
1091
#else
1092
  fprintf(as_file, "\t%s\t%d,%d\n", get_instruction(ins), dest, src);
1093
#endif
1094
}
1095
 
1096
 
7 7u83 1097
void rrrf_ins(Instruction_P ins, int src1, int src2, int dest)
2 7u83 1098
{
1099
  CHECKFREG(dest); CHECKFREG(src1); CHECKFREG(src2);
1100
 
1101
  clear_freg(dest);
1102
#ifdef DO_ASSEMBLER_MACROS
1103
  fprintf(as_file, "\t%s\t%s,%s,%s\n", get_instruction(ins), freg_macro(dest), freg_macro(src1), freg_macro(src2));
1104
#else
1105
  fprintf(as_file, "\t%s\t%d,%d,%d\n", get_instruction(ins), dest, src1, src2);
1106
#endif
1107
}
1108
 
7 7u83 1109
void rrrrf_ins(Instruction_P ins, int src1, int src2, int src3, int dest)
2 7u83 1110
{
1111
  CHECKFREG(dest); CHECKFREG(src1); CHECKFREG(src2); CHECKFREG(src3);
7 7u83 1112
 
2 7u83 1113
  clear_freg(dest);
1114
#ifdef DO_ASSEMBLER_MACROS
1115
  fprintf(as_file,"\t%s\t%s,%s,%s,%s\n",get_instruction(ins),freg_macro(dest),freg_macro(src1),freg_macro(src2),freg_macro(src3));
1116
#else
1117
  fprintf(as_file,"\t%s\t%d,%d,%d,%d\n",get_instruction(ins),dest,src1,src2,src3);
1118
#endif
1119
}
7 7u83 1120
void rlinm_ins(Instruction_P ins, int src1, int sl, unsigned int mask, int dest)
2 7u83 1121
{
1122
  CHECKREG(dest);CHECKREG(src1);
1123
  ASSERT(ins==i_rlinm||ins==i_rlinm_cr);
1124
  clear_reg(dest);
1125
#ifdef DO_ASSEMBLER_MACROS
1126
  fprintf(as_file,"\t%s\t%s,%s,%d,0x%x\n",get_instruction(ins),reg_macro(dest),reg_macro(src1),sl,mask);
1127
#else
1128
  fprintf(as_file,"\t%s\t%d,%d,%d,0x%x\n",get_instruction(ins),dest,src1,sl,mask);
1129
#endif
1130
}
1131
 
7 7u83 1132
void mfspr_ins(int spr, int dest)
1133
{
2 7u83 1134
  CHECKREG(dest);
1135
  clear_reg(dest);
1136
#ifdef DO_ASSEMBLER_MACROS
1137
  fprintf(as_file,"\t%s\t%s,%s\n",get_instruction(i_mfspr),reg_macro(dest),spr_macro(spr));
1138
#else
1139
  fprintf(as_file,"\t%s\t%d,%d\n",get_instruction(i_mfspr),dest,spr);
1140
#endif
1141
}
7 7u83 1142
void mtfsfi_ins(int fld, int imm)
2 7u83 1143
{
1144
  fprintf(as_file,"\t%s\t%d,%d\n",get_instruction(i_mtfsfi),fld,imm);
1145
}
7 7u83 1146
void mtfsb0_ins(int bit)
2 7u83 1147
{
1148
  ASSERT(bit>=0 && bit<=31);
1149
  fprintf(as_file,"\t%s\t%d\n",get_instruction(i_mtfsb0),bit);
1150
}
7 7u83 1151
void mtfsb1_ins(int bit)
2 7u83 1152
{
1153
  ASSERT(bit>=0 && bit<=31);
1154
  fprintf(as_file,"\t%s\t%d\n",get_instruction(i_mtfsb1),bit);
1155
}
7 7u83 1156
void mcrfs_ins(int a, int b)
2 7u83 1157
{
1158
  ASSERT(a>=0 && a<=7);
1159
  ASSERT(b>=0 && b<=7);
1160
#ifdef DO_ASSEMBLER_MACROS
1161
  fprintf(as_file,"\t%s\t%s,%d\n",get_instruction(i_mcrfs),cr_macro(a),b);
1162
#else
1163
  fprintf(as_file,"\t%s\t%d,%d\n",get_instruction(i_mcrfs),a,b);
1164
#endif
1165
}
7 7u83 1166
void lsi_ins(int src, int dest, int nb)
2 7u83 1167
{
1168
  fprintf(as_file,"\t%s\t%d,%d,%d\n",get_instruction(i_lsi),dest,src,nb);
1169
}
7 7u83 1170
void stsi_ins(int src, int dest, int nb)
2 7u83 1171
{
1172
  fprintf(as_file,"\t%s\t%d,%d,%d\n",get_instruction(i_stsi),src,dest,nb);
1173
}
7 7u83 1174
void comment(char *p)
2 7u83 1175
{
1176
#ifdef DEBUG_POWERTRANS
1177
  if (p==NIL)
1178
  {
1179
    fprintf(as_file,"\n");
1180
  }
1181
  else
1182
  {
1183
    fprintf(as_file,"        # %s\n",p);
1184
  }
1185
#else
1186
  fprintf(as_file,"\n");
1187
#endif
1188
  return;
1189
}
1190
 
7 7u83 1191
char * get_instruction(Instruction_P ins)
2 7u83 1192
{
1193
  char *w;
7 7u83 1194
  switch (architecture)
2 7u83 1195
  {
1196
   case COMMON_CODE:
1197
    w=ins->com;
1198
    break;
1199
   case RS6000_CODE:
1200
    w=ins->pwr;
1201
    break;
1202
   case POWERPC_CODE:
1203
    w=ins->ppc;
1204
    break;
1205
  };
1206
  return w;
1207
}