Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
145 halyavin 1
/*
2
 *  TMS320C67xx code generator for TCC
3
 *
4
 *  Copyright (c) 2001, 2002 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
 
6429 siemargl 21
#ifdef TARGET_DEFS_ONLY
145 halyavin 22
 
6429 siemargl 23
/* #define ASSEMBLY_LISTING_C67 */
24
 
145 halyavin 25
/* number of available registers */
26
#define NB_REGS            24
27
 
28
/* a register can belong to several classes. The classes must be
29
   sorted from more general to more precise (see gv2() code which does
30
   assumptions on it). */
31
#define RC_INT     0x0001	/* generic integer register */
32
#define RC_FLOAT   0x0002	/* generic float register */
33
#define RC_EAX     0x0004
34
#define RC_ST0     0x0008
35
#define RC_ECX     0x0010
36
#define RC_EDX     0x0020
37
#define RC_INT_BSIDE  0x00000040	/* generic integer register  on b side */
38
#define RC_C67_A4     0x00000100
39
#define RC_C67_A5     0x00000200
40
#define RC_C67_B4     0x00000400
41
#define RC_C67_B5     0x00000800
42
#define RC_C67_A6     0x00001000
43
#define RC_C67_A7     0x00002000
44
#define RC_C67_B6     0x00004000
45
#define RC_C67_B7     0x00008000
46
#define RC_C67_A8     0x00010000
47
#define RC_C67_A9     0x00020000
48
#define RC_C67_B8     0x00040000
49
#define RC_C67_B9     0x00080000
50
#define RC_C67_A10    0x00100000
51
#define RC_C67_A11    0x00200000
52
#define RC_C67_B10    0x00400000
53
#define RC_C67_B11    0x00800000
54
#define RC_C67_A12    0x01000000
55
#define RC_C67_A13    0x02000000
56
#define RC_C67_B12    0x04000000
57
#define RC_C67_B13    0x08000000
58
#define RC_IRET    RC_C67_A4	/* function return: integer register */
59
#define RC_LRET    RC_C67_A5	/* function return: second integer register */
60
#define RC_FRET    RC_C67_A4	/* function return: float register */
61
 
62
/* pretty names for the registers */
63
enum {
64
    TREG_EAX = 0,		// really A2
65
    TREG_ECX,			// really A3
66
    TREG_EDX,			// really B0
67
    TREG_ST0,			// really B1
68
    TREG_C67_A4,
69
    TREG_C67_A5,
70
    TREG_C67_B4,
71
    TREG_C67_B5,
72
    TREG_C67_A6,
73
    TREG_C67_A7,
74
    TREG_C67_B6,
75
    TREG_C67_B7,
76
    TREG_C67_A8,
77
    TREG_C67_A9,
78
    TREG_C67_B8,
79
    TREG_C67_B9,
80
    TREG_C67_A10,
81
    TREG_C67_A11,
82
    TREG_C67_B10,
83
    TREG_C67_B11,
84
    TREG_C67_A12,
85
    TREG_C67_A13,
86
    TREG_C67_B12,
87
    TREG_C67_B13,
88
};
89
 
6429 siemargl 90
/* return registers for function */
91
#define REG_IRET TREG_C67_A4	/* single word int return register */
92
#define REG_LRET TREG_C67_A5	/* second word return register (for long long) */
93
#define REG_FRET TREG_C67_A4	/* float return register */
94
 
95
/* defined if function parameters must be evaluated in reverse order */
96
/* #define INVERT_FUNC_PARAMS */
97
 
98
/* defined if structures are passed as pointers. Otherwise structures
99
   are directly pushed on stack. */
100
/* #define FUNC_STRUCT_PARAM_AS_PTR */
101
 
102
/* pointer size, in bytes */
103
#define PTR_SIZE 4
104
 
105
/* long double size and alignment, in bytes */
106
#define LDOUBLE_SIZE  12
107
#define LDOUBLE_ALIGN 4
108
/* maximum alignment (for aligned attribute support) */
109
#define MAX_ALIGN     8
110
 
111
/******************************************************/
112
/* ELF defines */
113
 
114
#define EM_TCC_TARGET EM_C60
115
 
116
/* relocation type for 32 bit data relocation */
117
#define R_DATA_32   R_C60_32
118
#define R_DATA_PTR  R_C60_32
119
#define R_JMP_SLOT  R_C60_JMP_SLOT
120
#define R_COPY      R_C60_COPY
121
 
122
#define ELF_START_ADDR 0x00000400
123
#define ELF_PAGE_SIZE  0x1000
124
 
125
/******************************************************/
126
#else /* ! TARGET_DEFS_ONLY */
127
/******************************************************/
128
#include "tcc.h"
129
 
130
ST_DATA const int reg_classes[NB_REGS] = {
131
    /* eax */ RC_INT | RC_FLOAT | RC_EAX,
132
    // only allow even regs for floats (allow for doubles)
145 halyavin 133
    /* ecx */ RC_INT | RC_ECX,
6429 siemargl 134
    /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
135
    // only allow even regs for floats (allow for doubles)
145 halyavin 136
    /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
137
    /* A4  */ RC_C67_A4,
138
    /* A5  */ RC_C67_A5,
139
    /* B4  */ RC_C67_B4,
140
    /* B5  */ RC_C67_B5,
141
    /* A6  */ RC_C67_A6,
142
    /* A7  */ RC_C67_A7,
143
    /* B6  */ RC_C67_B6,
144
    /* B7  */ RC_C67_B7,
145
    /* A8  */ RC_C67_A8,
146
    /* A9  */ RC_C67_A9,
147
    /* B8  */ RC_C67_B8,
148
    /* B9  */ RC_C67_B9,
149
    /* A10  */ RC_C67_A10,
150
    /* A11  */ RC_C67_A11,
151
    /* B10  */ RC_C67_B10,
152
    /* B11  */ RC_C67_B11,
153
    /* A12  */ RC_C67_A10,
154
    /* A13  */ RC_C67_A11,
155
    /* B12  */ RC_C67_B10,
156
    /* B13  */ RC_C67_B11
157
};
158
 
159
// although tcc thinks it is passing parameters on the stack,
160
// the C67 really passes up to the first 10 params in special
161
// regs or regs pairs (for 64 bit params).  So keep track of
162
// the stack offsets so we can translate to the appropriate
163
// reg (pair)
164
 
165
#define NoCallArgsPassedOnStack 10
166
int NoOfCurFuncArgs;
167
int TranslateStackToReg[NoCallArgsPassedOnStack];
168
int ParamLocOnStack[NoCallArgsPassedOnStack];
169
int TotalBytesPushedOnStack;
170
 
6429 siemargl 171
#ifndef FALSE
172
# define FALSE 0
173
# define TRUE 1
174
#endif
145 halyavin 175
 
6429 siemargl 176
#undef BOOL
177
#define BOOL int
145 halyavin 178
 
6429 siemargl 179
#define ALWAYS_ASSERT(x) \
180
do {\
181
   if (!(x))\
182
       tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
183
} while (0)
145 halyavin 184
 
185
/******************************************************/
186
static unsigned long func_sub_sp_offset;
187
static int func_ret_sub;
188
 
189
static BOOL C67_invert_test;
190
static int C67_compare_reg;
191
 
192
#ifdef ASSEMBLY_LISTING_C67
193
FILE *f = NULL;
194
#endif
195
 
196
void C67_g(int c)
197
{
198
    int ind1;
199
 
200
#ifdef ASSEMBLY_LISTING_C67
201
    fprintf(f, " %08X", c);
202
#endif
203
    ind1 = ind + 4;
204
    if (ind1 > (int) cur_text_section->data_allocated)
205
	section_realloc(cur_text_section, ind1);
206
    cur_text_section->data[ind] = c & 0xff;
207
    cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
208
    cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
209
    cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
210
    ind = ind1;
211
}
212
 
213
 
214
/* output a symbol and patch all calls to it */
215
void gsym_addr(int t, int a)
216
{
217
    int n, *ptr;
218
    while (t) {
219
	ptr = (int *) (cur_text_section->data + t);
220
	{
221
	    Sym *sym;
222
 
223
	    // extract 32 bit address from MVKH/MVKL
224
	    n = ((*ptr >> 7) & 0xffff);
225
	    n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
226
 
227
	    // define a label that will be relocated
228
 
229
	    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
230
	    greloc(cur_text_section, sym, t, R_C60LO16);
231
	    greloc(cur_text_section, sym, t + 4, R_C60HI16);
232
 
233
	    // clear out where the pointer was
234
 
235
	    *ptr &= ~(0xffff << 7);
236
	    *(ptr + 1) &= ~(0xffff << 7);
237
	}
238
	t = n;
239
    }
240
}
241
 
242
void gsym(int t)
243
{
244
    gsym_addr(t, ind);
245
}
246
 
247
// these are regs that tcc doesn't really know about,
6429 siemargl 248
// but assign them unique values so the mapping routines
249
// can distinguish them
145 halyavin 250
 
251
#define C67_A0 105
252
#define C67_SP 106
253
#define C67_B3 107
254
#define C67_FP 108
255
#define C67_B2 109
6429 siemargl 256
#define C67_CREG_ZERO -1	/* Special code for no condition reg test */
145 halyavin 257
 
258
 
259
int ConvertRegToRegClass(int r)
260
{
261
    // only works for A4-B13
262
 
263
    return RC_C67_A4 << (r - TREG_C67_A4);
264
}
265
 
266
 
267
// map TCC reg to C67 reg number
268
 
269
int C67_map_regn(int r)
270
{
271
    if (r == 0)			// normal tcc regs
272
	return 0x2;		// A2
273
    else if (r == 1)		// normal tcc regs
274
	return 3;		// A3
275
    else if (r == 2)		// normal tcc regs
276
	return 0;		// B0
277
    else if (r == 3)		// normal tcc regs
278
	return 1;		// B1
279
    else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)	// these form a pattern of alt pairs
280
	return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
281
    else if (r == C67_A0)
282
	return 0;		// set to A0 (offset reg)
283
    else if (r == C67_B2)
284
	return 2;		// set to B2 (offset reg)
285
    else if (r == C67_B3)
286
	return 3;		// set to B3 (return address reg)
287
    else if (r == C67_SP)
288
	return 15;		// set to SP (B15) (offset reg)
289
    else if (r == C67_FP)
290
	return 15;		// set to FP (A15) (offset reg)
291
    else if (r == C67_CREG_ZERO)
292
	return 0;		// Special code for no condition reg test
293
    else
294
	ALWAYS_ASSERT(FALSE);
295
 
296
    return 0;
297
}
298
 
299
// mapping from tcc reg number to
300
// C67 register to condition code field
301
//
302
// valid condition code regs are:
303
//
304
// tcc reg 2 ->B0 -> 1
305
// tcc reg 3 ->B1 -> 2
306
// tcc reg 0 -> A2 -> 5
307
// tcc reg 1 -> A3 -> X
308
// tcc reg      B2 -> 3
309
 
310
int C67_map_regc(int r)
311
{
312
    if (r == 0)			// normal tcc regs
313
	return 0x5;
314
    else if (r == 2)		// normal tcc regs
315
	return 0x1;
316
    else if (r == 3)		// normal tcc regs
317
	return 0x2;
318
    else if (r == C67_B2)	// normal tcc regs
319
	return 0x3;
320
    else if (r == C67_CREG_ZERO)
321
	return 0;		// Special code for no condition reg test
322
    else
323
	ALWAYS_ASSERT(FALSE);
324
 
325
    return 0;
326
}
327
 
328
 
329
// map TCC reg to C67 reg side A or B
330
 
331
int C67_map_regs(int r)
332
{
333
    if (r == 0)			// normal tcc regs
334
	return 0x0;
335
    else if (r == 1)		// normal tcc regs
336
	return 0x0;
337
    else if (r == 2)		// normal tcc regs
338
	return 0x1;
339
    else if (r == 3)		// normal tcc regs
340
	return 0x1;
341
    else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)	// these form a pattern of alt pairs
342
	return (r & 2) >> 1;
343
    else if (r == C67_A0)
344
	return 0;		// set to A side
345
    else if (r == C67_B2)
346
	return 1;		// set to B side
347
    else if (r == C67_B3)
348
	return 1;		// set to B side
349
    else if (r == C67_SP)
350
	return 0x1;		// set to SP (B15) B side
351
    else if (r == C67_FP)
352
	return 0x0;		// set to FP (A15) A side
353
    else
354
	ALWAYS_ASSERT(FALSE);
355
 
356
    return 0;
357
}
358
 
359
int C67_map_S12(char *s)
360
{
361
    if (strstr(s, ".S1") != NULL)
362
	return 0;
363
    else if (strcmp(s, ".S2"))
364
	return 1;
365
    else
366
	ALWAYS_ASSERT(FALSE);
367
 
368
    return 0;
369
}
370
 
371
int C67_map_D12(char *s)
372
{
373
    if (strstr(s, ".D1") != NULL)
374
	return 0;
375
    else if (strcmp(s, ".D2"))
376
	return 1;
377
    else
378
	ALWAYS_ASSERT(FALSE);
379
 
380
    return 0;
381
}
382
 
383
 
384
 
385
void C67_asm(char *s, int a, int b, int c)
386
{
387
    BOOL xpath;
388
 
389
#ifdef ASSEMBLY_LISTING_C67
390
    if (!f) {
391
	f = fopen("TCC67_out.txt", "wt");
392
    }
393
    fprintf(f, "%04X ", ind);
394
#endif
395
 
396
    if (strstr(s, "MVKL") == s) {
397
	C67_g((C67_map_regn(b) << 23) |
398
	      ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
399
    } else if (strstr(s, "MVKH") == s) {
400
	C67_g((C67_map_regn(b) << 23) |
401
	      (((a >> 16) & 0xffff) << 7) |
402
	      (0x1a << 2) | (C67_map_regs(b) << 1));
403
    } else if (strstr(s, "STW.D SP POST DEC") == s) {
404
	C67_g((C67_map_regn(a) << 23) |	//src
405
	      (15 << 18) |	//SP B15
406
	      (2 << 13) |	//ucst5 (must keep 8 byte boundary !!)
407
	      (0xa << 9) |	//mode a = post dec ucst
408
	      (0 << 8) |	//r (LDDW bit 0)
409
	      (1 << 7) |	//y D1/D2 use B side
410
	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
411
	      (1 << 2) |	//opcode
412
	      (C67_map_regs(a) << 1) |	//side of src
413
	      (0 << 0));	//parallel
414
    } else if (strstr(s, "STB.D *+SP[A0]") == s) {
415
	C67_g((C67_map_regn(a) << 23) |	//src
416
	      (15 << 18) |	//base reg A15
417
	      (0 << 13) |	//offset reg A0
418
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
419
	      (0 << 8) |	//r (LDDW bit 0)
420
	      (0 << 7) |	//y D1/D2 A side
421
	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
422
	      (1 << 2) |	//opcode
423
	      (C67_map_regs(a) << 1) |	//side of src
424
	      (0 << 0));	//parallel
425
    } else if (strstr(s, "STH.D *+SP[A0]") == s) {
426
	C67_g((C67_map_regn(a) << 23) |	//src
427
	      (15 << 18) |	//base reg A15
428
	      (0 << 13) |	//offset reg A0
429
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
430
	      (0 << 8) |	//r (LDDW bit 0)
431
	      (0 << 7) |	//y D1/D2 A side
432
	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
433
	      (1 << 2) |	//opcode
434
	      (C67_map_regs(a) << 1) |	//side of src
435
	      (0 << 0));	//parallel
436
    } else if (strstr(s, "STB.D *+SP[A0]") == s) {
437
	C67_g((C67_map_regn(a) << 23) |	//src
438
	      (15 << 18) |	//base reg A15
439
	      (0 << 13) |	//offset reg A0
440
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
441
	      (0 << 8) |	//r (LDDW bit 0)
442
	      (0 << 7) |	//y D1/D2 A side
443
	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
444
	      (1 << 2) |	//opcode
445
	      (C67_map_regs(a) << 1) |	//side of src
446
	      (0 << 0));	//parallel
447
    } else if (strstr(s, "STH.D *+SP[A0]") == s) {
448
	C67_g((C67_map_regn(a) << 23) |	//src
449
	      (15 << 18) |	//base reg A15
450
	      (0 << 13) |	//offset reg A0
451
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
452
	      (0 << 8) |	//r (LDDW bit 0)
453
	      (0 << 7) |	//y D1/D2 A side
454
	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
455
	      (1 << 2) |	//opcode
456
	      (C67_map_regs(a) << 1) |	//side of src
457
	      (0 << 0));	//parallel
458
    } else if (strstr(s, "STW.D *+SP[A0]") == s) {
459
	C67_g((C67_map_regn(a) << 23) |	//src
460
	      (15 << 18) |	//base reg A15
461
	      (0 << 13) |	//offset reg A0
462
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
463
	      (0 << 8) |	//r (LDDW bit 0)
464
	      (0 << 7) |	//y D1/D2 A side
465
	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
466
	      (1 << 2) |	//opcode
467
	      (C67_map_regs(a) << 1) |	//side of src
468
	      (0 << 0));	//parallel
469
    } else if (strstr(s, "STW.D *") == s) {
470
	C67_g((C67_map_regn(a) << 23) |	//src
471
	      (C67_map_regn(b) << 18) |	//base reg A0
472
	      (0 << 13) |	//cst5
473
	      (1 << 9) |	//mode 1 = pos cst offset
474
	      (0 << 8) |	//r (LDDW bit 0)
475
	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
476
	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
477
	      (1 << 2) |	//opcode
478
	      (C67_map_regs(a) << 1) |	//side of src
479
	      (0 << 0));	//parallel
480
    } else if (strstr(s, "STH.D *") == s) {
481
	C67_g((C67_map_regn(a) << 23) |	//src
482
	      (C67_map_regn(b) << 18) |	//base reg A0
483
	      (0 << 13) |	//cst5
484
	      (1 << 9) |	//mode 1 = pos cst offset
485
	      (0 << 8) |	//r (LDDW bit 0)
486
	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
487
	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
488
	      (1 << 2) |	//opcode
489
	      (C67_map_regs(a) << 1) |	//side of src
490
	      (0 << 0));	//parallel
491
    } else if (strstr(s, "STB.D *") == s) {
492
	C67_g((C67_map_regn(a) << 23) |	//src
493
	      (C67_map_regn(b) << 18) |	//base reg A0
494
	      (0 << 13) |	//cst5
495
	      (1 << 9) |	//mode 1 = pos cst offset
496
	      (0 << 8) |	//r (LDDW bit 0)
497
	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
498
	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
499
	      (1 << 2) |	//opcode
500
	      (C67_map_regs(a) << 1) |	//side of src
501
	      (0 << 0));	//parallel
502
    } else if (strstr(s, "STW.D +*") == s) {
503
	ALWAYS_ASSERT(c < 32);
504
	C67_g((C67_map_regn(a) << 23) |	//src
505
	      (C67_map_regn(b) << 18) |	//base reg A0
506
	      (c << 13) |	//cst5
507
	      (1 << 9) |	//mode 1 = pos cst offset
508
	      (0 << 8) |	//r (LDDW bit 0)
509
	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
510
	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
511
	      (1 << 2) |	//opcode
512
	      (C67_map_regs(a) << 1) |	//side of src
513
	      (0 << 0));	//parallel
514
    } else if (strstr(s, "LDW.D SP PRE INC") == s) {
515
	C67_g((C67_map_regn(a) << 23) |	//dst
516
	      (15 << 18) |	//base reg B15
517
	      (2 << 13) |	//ucst5 (must keep 8 byte boundary)
518
	      (9 << 9) |	//mode 9 = pre inc ucst5
519
	      (0 << 8) |	//r (LDDW bit 0)
520
	      (1 << 7) |	//y D1/D2  B side
521
	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
522
	      (1 << 2) |	//opcode
523
	      (C67_map_regs(a) << 1) |	//side of dst
524
	      (0 << 0));	//parallel
525
    } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
526
	C67_g((C67_map_regn(a) << 23) |	//dst
527
	      (15 << 18) |	//base reg B15
528
	      (1 << 13) |	//ucst5 (must keep 8 byte boundary)
529
	      (9 << 9) |	//mode 9 = pre inc ucst5
530
	      (1 << 8) |	//r (LDDW bit 1)
531
	      (1 << 7) |	//y D1/D2  B side
532
	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
533
	      (1 << 2) |	//opcode
534
	      (C67_map_regs(a) << 1) |	//side of dst
535
	      (0 << 0));	//parallel
536
    } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
537
	C67_g((C67_map_regn(a) << 23) |	//dst
538
	      (15 << 18) |	//base reg A15
539
	      (0 << 13) |	//offset reg A0
540
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
541
	      (0 << 8) |	//r (LDDW bit 0)
542
	      (0 << 7) |	//y D1/D2  A side
543
	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
544
	      (1 << 2) |	//opcode
545
	      (C67_map_regs(a) << 1) |	//side of dst
546
	      (0 << 0));	//parallel
547
    } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
548
	C67_g((C67_map_regn(a) << 23) |	//dst
549
	      (15 << 18) |	//base reg A15
550
	      (0 << 13) |	//offset reg A0
551
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
552
	      (1 << 8) |	//r (LDDW bit 1)
553
	      (0 << 7) |	//y D1/D2  A side
554
	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
555
	      (1 << 2) |	//opcode
556
	      (C67_map_regs(a) << 1) |	//side of dst
557
	      (0 << 0));	//parallel
558
    } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
559
	C67_g((C67_map_regn(a) << 23) |	//dst
560
	      (15 << 18) |	//base reg A15
561
	      (0 << 13) |	//offset reg A0
562
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
563
	      (0 << 8) |	//r (LDDW bit 0)
564
	      (0 << 7) |	//y D1/D2  A side
565
	      (4 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
566
	      (1 << 2) |	//opcode
567
	      (C67_map_regs(a) << 1) |	//side of dst
568
	      (0 << 0));	//parallel
569
    } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
570
	C67_g((C67_map_regn(a) << 23) |	//dst
571
	      (15 << 18) |	//base reg A15
572
	      (0 << 13) |	//offset reg A0
573
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
574
	      (0 << 8) |	//r (LDDW bit 0)
575
	      (0 << 7) |	//y D1/D2  A side
576
	      (2 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
577
	      (1 << 2) |	//opcode
578
	      (C67_map_regs(a) << 1) |	//side of dst
579
	      (0 << 0));	//parallel
580
    } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
581
	C67_g((C67_map_regn(a) << 23) |	//dst
582
	      (15 << 18) |	//base reg A15
583
	      (0 << 13) |	//offset reg A0
584
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
585
	      (0 << 8) |	//r (LDDW bit 0)
586
	      (0 << 7) |	//y D1/D2  A side
587
	      (0 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
588
	      (1 << 2) |	//opcode
589
	      (C67_map_regs(a) << 1) |	//side of dst
590
	      (0 << 0));	//parallel
591
    } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
592
	C67_g((C67_map_regn(a) << 23) |	//dst
593
	      (15 << 18) |	//base reg A15
594
	      (0 << 13) |	//offset reg A0
595
	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
596
	      (0 << 8) |	//r (LDDW bit 0)
597
	      (0 << 7) |	//y D1/D2  A side
598
	      (1 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
599
	      (1 << 2) |	//opcode
600
	      (C67_map_regs(a) << 1) |	//side of dst
601
	      (0 << 0));	//parallel
602
    } else if (strstr(s, "LDW.D *") == s) {
603
	C67_g((C67_map_regn(b) << 23) |	//dst
604
	      (C67_map_regn(a) << 18) |	//base reg A15
605
	      (0 << 13) |	//cst5
606
	      (1 << 9) |	//mode 1 = pos cst offset
607
	      (0 << 8) |	//r (LDDW bit 0)
608
	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
609
	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
610
	      (1 << 2) |	//opcode
611
	      (C67_map_regs(b) << 1) |	//side of dst
612
	      (0 << 0));	//parallel
613
    } else if (strstr(s, "LDDW.D *") == s) {
614
	C67_g((C67_map_regn(b) << 23) |	//dst
615
	      (C67_map_regn(a) << 18) |	//base reg A15
616
	      (0 << 13) |	//cst5
617
	      (1 << 9) |	//mode 1 = pos cst offset
618
	      (1 << 8) |	//r (LDDW bit 1)
619
	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
620
	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
621
	      (1 << 2) |	//opcode
622
	      (C67_map_regs(b) << 1) |	//side of dst
623
	      (0 << 0));	//parallel
624
    } else if (strstr(s, "LDH.D *") == s) {
625
	C67_g((C67_map_regn(b) << 23) |	//dst
626
	      (C67_map_regn(a) << 18) |	//base reg A15
627
	      (0 << 13) |	//cst5
628
	      (1 << 9) |	//mode 1 = pos cst offset
629
	      (0 << 8) |	//r (LDDW bit 0)
630
	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
631
	      (4 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
632
	      (1 << 2) |	//opcode
633
	      (C67_map_regs(b) << 1) |	//side of dst
634
	      (0 << 0));	//parallel
635
    } else if (strstr(s, "LDB.D *") == s) {
636
	C67_g((C67_map_regn(b) << 23) |	//dst
637
	      (C67_map_regn(a) << 18) |	//base reg A15
638
	      (0 << 13) |	//cst5
639
	      (1 << 9) |	//mode 1 = pos cst offset
640
	      (0 << 8) |	//r (LDDW bit 0)
641
	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
642
	      (2 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
643
	      (1 << 2) |	//opcode
644
	      (C67_map_regs(b) << 1) |	//side of dst
645
	      (0 << 0));	//parallel
646
    } else if (strstr(s, "LDHU.D *") == s) {
647
	C67_g((C67_map_regn(b) << 23) |	//dst
648
	      (C67_map_regn(a) << 18) |	//base reg A15
649
	      (0 << 13) |	//cst5
650
	      (1 << 9) |	//mode 1 = pos cst offset
651
	      (0 << 8) |	//r (LDDW bit 0)
652
	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
653
	      (0 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
654
	      (1 << 2) |	//opcode
655
	      (C67_map_regs(b) << 1) |	//side of dst
656
	      (0 << 0));	//parallel
657
    } else if (strstr(s, "LDBU.D *") == s) {
658
	C67_g((C67_map_regn(b) << 23) |	//dst
659
	      (C67_map_regn(a) << 18) |	//base reg A15
660
	      (0 << 13) |	//cst5
661
	      (1 << 9) |	//mode 1 = pos cst offset
662
	      (0 << 8) |	//r (LDDW bit 0)
663
	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
664
	      (1 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
665
	      (1 << 2) |	//opcode
666
	      (C67_map_regs(b) << 1) |	//side of dst
667
	      (0 << 0));	//parallel
668
    } else if (strstr(s, "LDW.D +*") == s) {
669
	C67_g((C67_map_regn(b) << 23) |	//dst
670
	      (C67_map_regn(a) << 18) |	//base reg A15
671
	      (1 << 13) |	//cst5
672
	      (1 << 9) |	//mode 1 = pos cst offset
673
	      (0 << 8) |	//r (LDDW bit 0)
674
	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
675
	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
676
	      (1 << 2) |	//opcode
677
	      (C67_map_regs(b) << 1) |	//side of dst
678
	      (0 << 0));	//parallel
679
    } else if (strstr(s, "CMPLTSP") == s) {
680
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
681
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
682
 
683
	C67_g((C67_map_regn(c) << 23) |	//dst
684
	      (C67_map_regn(b) << 18) |	//src2
685
	      (C67_map_regn(a) << 13) |	//src1
686
	      (xpath << 12) |	//x use cross path for src2
687
	      (0x3a << 6) |	//opcode
688
	      (0x8 << 2) |	//opcode fixed
689
	      (C67_map_regs(c) << 1) |	//side for reg c
690
	      (0 << 0));	//parallel
691
    } else if (strstr(s, "CMPGTSP") == s) {
692
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
693
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
694
 
695
	C67_g((C67_map_regn(c) << 23) |	//dst
696
	      (C67_map_regn(b) << 18) |	//src2
697
	      (C67_map_regn(a) << 13) |	//src1
698
	      (xpath << 12) |	//x use cross path for src2
699
	      (0x39 << 6) |	//opcode
700
	      (0x8 << 2) |	//opcode fixed
701
	      (C67_map_regs(c) << 1) |	//side for reg c
702
	      (0 << 0));	//parallel
703
    } else if (strstr(s, "CMPEQSP") == s) {
704
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
705
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
706
 
707
	C67_g((C67_map_regn(c) << 23) |	//dst
708
	      (C67_map_regn(b) << 18) |	//src2
709
	      (C67_map_regn(a) << 13) |	//src1
710
	      (xpath << 12) |	//x use cross path for src2
711
	      (0x38 << 6) |	//opcode
712
	      (0x8 << 2) |	//opcode fixed
713
	      (C67_map_regs(c) << 1) |	//side for reg c
714
	      (0 << 0));	//parallel
715
    }
716
 
717
    else if (strstr(s, "CMPLTDP") == s) {
718
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
719
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
720
 
721
	C67_g((C67_map_regn(c) << 23) |	//dst
722
	      (C67_map_regn(b) << 18) |	//src2
723
	      (C67_map_regn(a) << 13) |	//src1
724
	      (xpath << 12) |	//x use cross path for src2
725
	      (0x2a << 6) |	//opcode
726
	      (0x8 << 2) |	//opcode fixed
727
	      (C67_map_regs(c) << 1) |	//side for reg c
728
	      (0 << 0));	//parallel
729
    } else if (strstr(s, "CMPGTDP") == s) {
730
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
731
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
732
 
733
	C67_g((C67_map_regn(c) << 23) |	//dst
734
	      (C67_map_regn(b) << 18) |	//src2
735
	      (C67_map_regn(a) << 13) |	//src1
736
	      (xpath << 12) |	//x use cross path for src2
737
	      (0x29 << 6) |	//opcode
738
	      (0x8 << 2) |	//opcode fixed
739
	      (C67_map_regs(c) << 1) |	//side for reg c
740
	      (0 << 0));	//parallel
741
    } else if (strstr(s, "CMPEQDP") == s) {
742
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
743
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
744
 
745
	C67_g((C67_map_regn(c) << 23) |	//dst
746
	      (C67_map_regn(b) << 18) |	//src2
747
	      (C67_map_regn(a) << 13) |	//src1
748
	      (xpath << 12) |	//x use cross path for src2
749
	      (0x28 << 6) |	//opcode
750
	      (0x8 << 2) |	//opcode fixed
751
	      (C67_map_regs(c) << 1) |	//side for reg c
752
	      (0 << 0));	//parallel
753
    } else if (strstr(s, "CMPLT") == s) {
754
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
755
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
756
 
757
	C67_g((C67_map_regn(c) << 23) |	//dst
758
	      (C67_map_regn(b) << 18) |	//src2
759
	      (C67_map_regn(a) << 13) |	//src1
760
	      (xpath << 12) |	//x use cross path for src2
761
	      (0x57 << 5) |	//opcode
762
	      (0x6 << 2) |	//opcode fixed
763
	      (C67_map_regs(c) << 1) |	//side for reg c
764
	      (0 << 0));	//parallel
765
    } else if (strstr(s, "CMPGT") == s) {
766
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
767
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
768
 
769
	C67_g((C67_map_regn(c) << 23) |	//dst
770
	      (C67_map_regn(b) << 18) |	//src2
771
	      (C67_map_regn(a) << 13) |	//src1
772
	      (xpath << 12) |	//x use cross path for src2
773
	      (0x47 << 5) |	//opcode
774
	      (0x6 << 2) |	//opcode fixed
775
	      (C67_map_regs(c) << 1) |	//side for reg c
776
	      (0 << 0));	//parallel
777
    } else if (strstr(s, "CMPEQ") == s) {
778
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
779
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
780
 
781
	C67_g((C67_map_regn(c) << 23) |	//dst
782
	      (C67_map_regn(b) << 18) |	//src2
783
	      (C67_map_regn(a) << 13) |	//src1
784
	      (xpath << 12) |	//x use cross path for src2
785
	      (0x53 << 5) |	//opcode
786
	      (0x6 << 2) |	//opcode fixed
787
	      (C67_map_regs(c) << 1) |	//side for reg c
788
	      (0 << 0));	//parallel
789
    } else if (strstr(s, "CMPLTU") == s) {
790
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
791
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
792
 
793
	C67_g((C67_map_regn(c) << 23) |	//dst
794
	      (C67_map_regn(b) << 18) |	//src2
795
	      (C67_map_regn(a) << 13) |	//src1
796
	      (xpath << 12) |	//x use cross path for src2
797
	      (0x5f << 5) |	//opcode
798
	      (0x6 << 2) |	//opcode fixed
799
	      (C67_map_regs(c) << 1) |	//side for reg c
800
	      (0 << 0));	//parallel
801
    } else if (strstr(s, "CMPGTU") == s) {
802
	xpath = C67_map_regs(a) ^ C67_map_regs(b);
803
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
804
 
805
	C67_g((C67_map_regn(c) << 23) |	//dst
806
	      (C67_map_regn(b) << 18) |	//src2
807
	      (C67_map_regn(a) << 13) |	//src1
808
	      (xpath << 12) |	//x use cross path for src2
809
	      (0x4f << 5) |	//opcode
810
	      (0x6 << 2) |	//opcode fixed
811
	      (C67_map_regs(c) << 1) |	//side for reg c
812
	      (0 << 0));	//parallel
813
    } else if (strstr(s, "B DISP") == s) {
814
	C67_g((0 << 29) |	//creg
815
	      (0 << 28) |	//z
816
	      (a << 7) |	//cnst
817
	      (0x4 << 2) |	//opcode fixed
818
	      (0 << 1) |	//S0/S1
819
	      (0 << 0));	//parallel
820
    } else if (strstr(s, "B.") == s) {
821
	xpath = C67_map_regs(c) ^ 1;
822
 
823
	C67_g((C67_map_regc(b) << 29) |	//creg
824
	      (a << 28) |	//inv
825
	      (0 << 23) |	//dst
826
	      (C67_map_regn(c) << 18) |	//src2
827
	      (0 << 13) |	//
828
	      (xpath << 12) |	//x cross path if !B side
829
	      (0xd << 6) |	//opcode
830
	      (0x8 << 2) |	//opcode fixed
831
	      (1 << 1) |	//must be S2
832
	      (0 << 0));	//parallel
833
    } else if (strstr(s, "MV.L") == s) {
834
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
835
 
836
	C67_g((0 << 29) |	//creg
837
	      (0 << 28) |	//inv
838
	      (C67_map_regn(c) << 23) |	//dst
839
	      (C67_map_regn(b) << 18) |	//src2
840
	      (0 << 13) |	//src1 (cst5)
841
	      (xpath << 12) |	//x cross path if opposite sides
842
	      (0x2 << 5) |	//opcode
843
	      (0x6 << 2) |	//opcode fixed
844
	      (C67_map_regs(c) << 1) |	//side of dest
845
	      (0 << 0));	//parallel
846
    } else if (strstr(s, "SPTRUNC.L") == s) {
847
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
848
 
849
	C67_g((0 << 29) |	//creg
850
	      (0 << 28) |	//inv
851
	      (C67_map_regn(c) << 23) |	//dst
852
	      (C67_map_regn(b) << 18) |	//src2
853
	      (0 << 13) |	//src1 NA
854
	      (xpath << 12) |	//x cross path if opposite sides
855
	      (0xb << 5) |	//opcode
856
	      (0x6 << 2) |	//opcode fixed
857
	      (C67_map_regs(c) << 1) |	//side of dest
858
	      (0 << 0));	//parallel
859
    } else if (strstr(s, "DPTRUNC.L") == s) {
860
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
861
 
862
	C67_g((0 << 29) |	//creg
863
	      (0 << 28) |	//inv
864
	      (C67_map_regn(c) << 23) |	//dst
865
	      ((C67_map_regn(b) + 1) << 18) |	//src2   WEIRD CPU must specify odd reg for some reason
866
	      (0 << 13) |	//src1 NA
867
	      (xpath << 12) |	//x cross path if opposite sides
868
	      (0x1 << 5) |	//opcode
869
	      (0x6 << 2) |	//opcode fixed
870
	      (C67_map_regs(c) << 1) |	//side of dest
871
	      (0 << 0));	//parallel
872
    } else if (strstr(s, "INTSP.L") == s) {
873
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
874
 
875
	C67_g((0 << 29) |	//creg
876
	      (0 << 28) |	//inv
877
	      (C67_map_regn(c) << 23) |	//dst
878
	      (C67_map_regn(b) << 18) |	//src2
879
	      (0 << 13) |	//src1 NA
880
	      (xpath << 12) |	//x cross path if opposite sides
881
	      (0x4a << 5) |	//opcode
882
	      (0x6 << 2) |	//opcode fixed
883
	      (C67_map_regs(c) << 1) |	//side of dest
884
	      (0 << 0));	//parallel
885
    } else if (strstr(s, "INTSPU.L") == s) {
886
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
887
 
888
	C67_g((0 << 29) |	//creg
889
	      (0 << 28) |	//inv
890
	      (C67_map_regn(c) << 23) |	//dst
891
	      (C67_map_regn(b) << 18) |	//src2
892
	      (0 << 13) |	//src1 NA
893
	      (xpath << 12) |	//x cross path if opposite sides
894
	      (0x49 << 5) |	//opcode
895
	      (0x6 << 2) |	//opcode fixed
896
	      (C67_map_regs(c) << 1) |	//side of dest
897
	      (0 << 0));	//parallel
898
    } else if (strstr(s, "INTDP.L") == s) {
899
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
900
 
901
	C67_g((0 << 29) |	//creg
902
	      (0 << 28) |	//inv
903
	      (C67_map_regn(c) << 23) |	//dst
904
	      (C67_map_regn(b) << 18) |	//src2
905
	      (0 << 13) |	//src1 NA
906
	      (xpath << 12) |	//x cross path if opposite sides
907
	      (0x39 << 5) |	//opcode
908
	      (0x6 << 2) |	//opcode fixed
909
	      (C67_map_regs(c) << 1) |	//side of dest
910
	      (0 << 0));	//parallel
911
    } else if (strstr(s, "INTDPU.L") == s) {
912
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
913
 
914
	C67_g((0 << 29) |	//creg
915
	      (0 << 28) |	//inv
916
	      (C67_map_regn(c) << 23) |	//dst
917
	      ((C67_map_regn(b) + 1) << 18) |	//src2   WEIRD CPU must specify odd reg for some reason
918
	      (0 << 13) |	//src1 NA
919
	      (xpath << 12) |	//x cross path if opposite sides
920
	      (0x3b << 5) |	//opcode
921
	      (0x6 << 2) |	//opcode fixed
922
	      (C67_map_regs(c) << 1) |	//side of dest
923
	      (0 << 0));	//parallel
924
    } else if (strstr(s, "SPDP.L") == s) {
925
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
926
 
927
	C67_g((0 << 29) |	//creg
928
	      (0 << 28) |	//inv
929
	      (C67_map_regn(c) << 23) |	//dst
930
	      (C67_map_regn(b) << 18) |	//src2
931
	      (0 << 13) |	//src1 NA
932
	      (xpath << 12) |	//x cross path if opposite sides
933
	      (0x2 << 6) |	//opcode
934
	      (0x8 << 2) |	//opcode fixed
935
	      (C67_map_regs(c) << 1) |	//side of dest
936
	      (0 << 0));	//parallel
937
    } else if (strstr(s, "DPSP.L") == s) {
938
	ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
939
 
940
	C67_g((0 << 29) |	//creg
941
	      (0 << 28) |	//inv
942
	      (C67_map_regn(c) << 23) |	//dst
943
	      ((C67_map_regn(b) + 1) << 18) |	//src2 WEIRD CPU must specify odd reg for some reason
944
	      (0 << 13) |	//src1 NA
945
	      (0 << 12) |	//x cross path if opposite sides
946
	      (0x9 << 5) |	//opcode
947
	      (0x6 << 2) |	//opcode fixed
948
	      (C67_map_regs(c) << 1) |	//side of dest
949
	      (0 << 0));	//parallel
950
    } else if (strstr(s, "ADD.L") == s) {
951
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
952
 
953
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
954
 
955
	C67_g((0 << 29) |	//creg
956
	      (0 << 28) |	//inv
957
	      (C67_map_regn(c) << 23) |	//dst
958
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
959
	      (C67_map_regn(a) << 13) |	//src1
960
	      (xpath << 12) |	//x cross path if opposite sides
961
	      (0x3 << 5) |	//opcode
962
	      (0x6 << 2) |	//opcode fixed
963
	      (C67_map_regs(c) << 1) |	//side of dest
964
	      (0 << 0));	//parallel
965
    } else if (strstr(s, "SUB.L") == s) {
966
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
967
 
968
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
969
 
970
	C67_g((0 << 29) |	//creg
971
	      (0 << 28) |	//inv
972
	      (C67_map_regn(c) << 23) |	//dst
973
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
974
	      (C67_map_regn(a) << 13) |	//src1
975
	      (xpath << 12) |	//x cross path if opposite sides
976
	      (0x7 << 5) |	//opcode
977
	      (0x6 << 2) |	//opcode fixed
978
	      (C67_map_regs(c) << 1) |	//side of dest
979
	      (0 << 0));	//parallel
980
    } else if (strstr(s, "OR.L") == s) {
981
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
982
 
983
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
984
 
985
	C67_g((0 << 29) |	//creg
986
	      (0 << 28) |	//inv
987
	      (C67_map_regn(c) << 23) |	//dst
988
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
989
	      (C67_map_regn(a) << 13) |	//src1
990
	      (xpath << 12) |	//x cross path if opposite sides
991
	      (0x7f << 5) |	//opcode
992
	      (0x6 << 2) |	//opcode fixed
993
	      (C67_map_regs(c) << 1) |	//side of dest
994
	      (0 << 0));	//parallel
995
    } else if (strstr(s, "AND.L") == s) {
996
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
997
 
998
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
999
 
1000
	C67_g((0 << 29) |	//creg
1001
	      (0 << 28) |	//inv
1002
	      (C67_map_regn(c) << 23) |	//dst
1003
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1004
	      (C67_map_regn(a) << 13) |	//src1
1005
	      (xpath << 12) |	//x cross path if opposite sides
1006
	      (0x7b << 5) |	//opcode
1007
	      (0x6 << 2) |	//opcode fixed
1008
	      (C67_map_regs(c) << 1) |	//side of dest
1009
	      (0 << 0));	//parallel
1010
    } else if (strstr(s, "XOR.L") == s) {
1011
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1012
 
1013
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1014
 
1015
	C67_g((0 << 29) |	//creg
1016
	      (0 << 28) |	//inv
1017
	      (C67_map_regn(c) << 23) |	//dst
1018
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1019
	      (C67_map_regn(a) << 13) |	//src1
1020
	      (xpath << 12) |	//x cross path if opposite sides
1021
	      (0x6f << 5) |	//opcode
1022
	      (0x6 << 2) |	//opcode fixed
1023
	      (C67_map_regs(c) << 1) |	//side of dest
1024
	      (0 << 0));	//parallel
1025
    } else if (strstr(s, "ADDSP.L") == s) {
1026
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1027
 
1028
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1029
 
1030
	C67_g((0 << 29) |	//creg
1031
	      (0 << 28) |	//inv
1032
	      (C67_map_regn(c) << 23) |	//dst
1033
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1034
	      (C67_map_regn(a) << 13) |	//src1
1035
	      (xpath << 12) |	//x cross path if opposite sides
1036
	      (0x10 << 5) |	//opcode
1037
	      (0x6 << 2) |	//opcode fixed
1038
	      (C67_map_regs(c) << 1) |	//side of dest
1039
	      (0 << 0));	//parallel
1040
    } else if (strstr(s, "ADDDP.L") == s) {
1041
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1042
 
1043
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1044
 
1045
	C67_g((0 << 29) |	//creg
1046
	      (0 << 28) |	//inv
1047
	      (C67_map_regn(c) << 23) |	//dst
1048
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1049
	      (C67_map_regn(a) << 13) |	//src1
1050
	      (xpath << 12) |	//x cross path if opposite sides
1051
	      (0x18 << 5) |	//opcode
1052
	      (0x6 << 2) |	//opcode fixed
1053
	      (C67_map_regs(c) << 1) |	//side of dest
1054
	      (0 << 0));	//parallel
1055
    } else if (strstr(s, "SUBSP.L") == s) {
1056
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1057
 
1058
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1059
 
1060
	C67_g((0 << 29) |	//creg
1061
	      (0 << 28) |	//inv
1062
	      (C67_map_regn(c) << 23) |	//dst
1063
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1064
	      (C67_map_regn(a) << 13) |	//src1
1065
	      (xpath << 12) |	//x cross path if opposite sides
1066
	      (0x11 << 5) |	//opcode
1067
	      (0x6 << 2) |	//opcode fixed
1068
	      (C67_map_regs(c) << 1) |	//side of dest
1069
	      (0 << 0));	//parallel
1070
    } else if (strstr(s, "SUBDP.L") == s) {
1071
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1072
 
1073
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1074
 
1075
	C67_g((0 << 29) |	//creg
1076
	      (0 << 28) |	//inv
1077
	      (C67_map_regn(c) << 23) |	//dst
1078
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1079
	      (C67_map_regn(a) << 13) |	//src1
1080
	      (xpath << 12) |	//x cross path if opposite sides
1081
	      (0x19 << 5) |	//opcode
1082
	      (0x6 << 2) |	//opcode fixed
1083
	      (C67_map_regs(c) << 1) |	//side of dest
1084
	      (0 << 0));	//parallel
1085
    } else if (strstr(s, "MPYSP.M") == s) {
1086
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1087
 
1088
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1089
 
1090
	C67_g((0 << 29) |	//creg
1091
	      (0 << 28) |	//inv
1092
	      (C67_map_regn(c) << 23) |	//dst
1093
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1094
	      (C67_map_regn(a) << 13) |	//src1
1095
	      (xpath << 12) |	//x cross path if opposite sides
1096
	      (0x1c << 7) |	//opcode
1097
	      (0x0 << 2) |	//opcode fixed
1098
	      (C67_map_regs(c) << 1) |	//side of dest
1099
	      (0 << 0));	//parallel
1100
    } else if (strstr(s, "MPYDP.M") == s) {
1101
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1102
 
1103
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1104
 
1105
	C67_g((0 << 29) |	//creg
1106
	      (0 << 28) |	//inv
1107
	      (C67_map_regn(c) << 23) |	//dst
1108
	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1109
	      (C67_map_regn(a) << 13) |	//src1
1110
	      (xpath << 12) |	//x cross path if opposite sides
1111
	      (0x0e << 7) |	//opcode
1112
	      (0x0 << 2) |	//opcode fixed
1113
	      (C67_map_regs(c) << 1) |	//side of dest
1114
	      (0 << 0));	//parallel
1115
    } else if (strstr(s, "MPYI.M") == s) {
1116
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1117
 
1118
	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1119
 
1120
	C67_g((0 << 29) |	//creg
1121
	      (0 << 28) |	//inv
1122
	      (C67_map_regn(c) << 23) |	//dst
1123
	      (C67_map_regn(b) << 18) |	//src2
1124
	      (C67_map_regn(a) << 13) |	//src1 (cst5)
1125
	      (xpath << 12) |	//x cross path if opposite sides
1126
	      (0x4 << 7) |	//opcode
1127
	      (0x0 << 2) |	//opcode fixed
1128
	      (C67_map_regs(c) << 1) |	//side of dest
1129
	      (0 << 0));	//parallel
1130
    } else if (strstr(s, "SHR.S") == s) {
1131
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1132
 
1133
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1134
 
1135
	C67_g((0 << 29) |	//creg
1136
	      (0 << 28) |	//inv
1137
	      (C67_map_regn(c) << 23) |	//dst
1138
	      (C67_map_regn(b) << 18) |	//src2
1139
	      (C67_map_regn(a) << 13) |	//src1
1140
	      (xpath << 12) |	//x cross path if opposite sides
1141
	      (0x37 << 6) |	//opcode
1142
	      (0x8 << 2) |	//opcode fixed
1143
	      (C67_map_regs(c) << 1) |	//side of dest
1144
	      (0 << 0));	//parallel
1145
    } else if (strstr(s, "SHRU.S") == s) {
1146
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1147
 
1148
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1149
 
1150
	C67_g((0 << 29) |	//creg
1151
	      (0 << 28) |	//inv
1152
	      (C67_map_regn(c) << 23) |	//dst
1153
	      (C67_map_regn(b) << 18) |	//src2
1154
	      (C67_map_regn(a) << 13) |	//src1
1155
	      (xpath << 12) |	//x cross path if opposite sides
1156
	      (0x27 << 6) |	//opcode
1157
	      (0x8 << 2) |	//opcode fixed
1158
	      (C67_map_regs(c) << 1) |	//side of dest
1159
	      (0 << 0));	//parallel
1160
    } else if (strstr(s, "SHL.S") == s) {
1161
	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1162
 
1163
	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1164
 
1165
	C67_g((0 << 29) |	//creg
1166
	      (0 << 28) |	//inv
1167
	      (C67_map_regn(c) << 23) |	//dst
1168
	      (C67_map_regn(b) << 18) |	//src2
1169
	      (C67_map_regn(a) << 13) |	//src1
1170
	      (xpath << 12) |	//x cross path if opposite sides
1171
	      (0x33 << 6) |	//opcode
1172
	      (0x8 << 2) |	//opcode fixed
1173
	      (C67_map_regs(c) << 1) |	//side of dest
1174
	      (0 << 0));	//parallel
1175
    } else if (strstr(s, "||ADDK") == s) {
1176
	xpath = 0;		// no xpath required just use the side of the src/dst
1177
 
1178
	C67_g((0 << 29) |	//creg
1179
	      (0 << 28) |	//inv
1180
	      (C67_map_regn(b) << 23) |	//dst
1181
	      (a << 07) |	//scst16
1182
	      (0x14 << 2) |	//opcode fixed
1183
	      (C67_map_regs(b) << 1) |	//side of dst
1184
	      (1 << 0));	//parallel
1185
    } else if (strstr(s, "ADDK") == s) {
1186
	xpath = 0;		// no xpath required just use the side of the src/dst
1187
 
1188
	C67_g((0 << 29) |	//creg
1189
	      (0 << 28) |	//inv
1190
	      (C67_map_regn(b) << 23) |	//dst
1191
	      (a << 07) |	//scst16
1192
	      (0x14 << 2) |	//opcode fixed
1193
	      (C67_map_regs(b) << 1) |	//side of dst
1194
	      (0 << 0));	//parallel
1195
    } else if (strstr(s, "NOP") == s) {
1196
	C67_g(((a - 1) << 13) |	//no of cycles
1197
	      (0 << 0));	//parallel
1198
    } else
1199
	ALWAYS_ASSERT(FALSE);
1200
 
1201
#ifdef ASSEMBLY_LISTING_C67
1202
    fprintf(f, " %s %d %d %d\n", s, a, b, c);
1203
#endif
1204
 
1205
}
1206
 
1207
//r=reg to load, fr=from reg, symbol for relocation, constant
1208
 
1209
void C67_MVKL(int r, int fc)
1210
{
1211
    C67_asm("MVKL.", fc, r, 0);
1212
}
1213
 
1214
void C67_MVKH(int r, int fc)
1215
{
1216
    C67_asm("MVKH.", fc, r, 0);
1217
}
1218
 
1219
void C67_STB_SP_A0(int r)
1220
{
1221
    C67_asm("STB.D *+SP[A0]", r, 0, 0);	// STB  r,*+SP[A0]
1222
}
1223
 
1224
void C67_STH_SP_A0(int r)
1225
{
1226
    C67_asm("STH.D *+SP[A0]", r, 0, 0);	// STH  r,*+SP[A0]
1227
}
1228
 
1229
void C67_STW_SP_A0(int r)
1230
{
1231
    C67_asm("STW.D *+SP[A0]", r, 0, 0);	// STW  r,*+SP[A0]
1232
}
1233
 
1234
void C67_STB_PTR(int r, int r2)
1235
{
1236
    C67_asm("STB.D *", r, r2, 0);	// STB  r, *r2
1237
}
1238
 
1239
void C67_STH_PTR(int r, int r2)
1240
{
1241
    C67_asm("STH.D *", r, r2, 0);	// STH  r, *r2
1242
}
1243
 
1244
void C67_STW_PTR(int r, int r2)
1245
{
1246
    C67_asm("STW.D *", r, r2, 0);	// STW  r, *r2
1247
}
1248
 
1249
void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1250
{
1251
    C67_asm("STW.D +*", r, r2, n);	// STW  r, *+r2
1252
}
1253
 
1254
void C67_PUSH(int r)
1255
{
1256
    C67_asm("STW.D SP POST DEC", r, 0, 0);	// STW  r,*SP--
1257
}
1258
 
1259
void C67_LDW_SP_A0(int r)
1260
{
1261
    C67_asm("LDW.D *+SP[A0]", r, 0, 0);	// LDW  *+SP[A0],r
1262
}
1263
 
1264
void C67_LDDW_SP_A0(int r)
1265
{
1266
    C67_asm("LDDW.D *+SP[A0]", r, 0, 0);	// LDDW  *+SP[A0],r
1267
}
1268
 
1269
void C67_LDH_SP_A0(int r)
1270
{
1271
    C67_asm("LDH.D *+SP[A0]", r, 0, 0);	// LDH  *+SP[A0],r
1272
}
1273
 
1274
void C67_LDB_SP_A0(int r)
1275
{
1276
    C67_asm("LDB.D *+SP[A0]", r, 0, 0);	// LDB  *+SP[A0],r
1277
}
1278
 
1279
void C67_LDHU_SP_A0(int r)
1280
{
1281
    C67_asm("LDHU.D *+SP[A0]", r, 0, 0);	// LDHU  *+SP[A0],r
1282
}
1283
 
1284
void C67_LDBU_SP_A0(int r)
1285
{
1286
    C67_asm("LDBU.D *+SP[A0]", r, 0, 0);	// LDBU  *+SP[A0],r
1287
}
1288
 
1289
void C67_LDW_PTR(int r, int r2)
1290
{
1291
    C67_asm("LDW.D *", r, r2, 0);	// LDW  *r,r2
1292
}
1293
 
1294
void C67_LDDW_PTR(int r, int r2)
1295
{
1296
    C67_asm("LDDW.D *", r, r2, 0);	// LDDW  *r,r2
1297
}
1298
 
1299
void C67_LDH_PTR(int r, int r2)
1300
{
1301
    C67_asm("LDH.D *", r, r2, 0);	// LDH  *r,r2
1302
}
1303
 
1304
void C67_LDB_PTR(int r, int r2)
1305
{
1306
    C67_asm("LDB.D *", r, r2, 0);	// LDB  *r,r2
1307
}
1308
 
1309
void C67_LDHU_PTR(int r, int r2)
1310
{
1311
    C67_asm("LDHU.D *", r, r2, 0);	// LDHU  *r,r2
1312
}
1313
 
1314
void C67_LDBU_PTR(int r, int r2)
1315
{
1316
    C67_asm("LDBU.D *", r, r2, 0);	// LDBU  *r,r2
1317
}
1318
 
1319
void C67_LDW_PTR_PRE_INC(int r, int r2)
1320
{
1321
    C67_asm("LDW.D +*", r, r2, 0);	// LDW  *+r,r2
1322
}
1323
 
1324
void C67_POP(int r)
1325
{
1326
    C67_asm("LDW.D SP PRE INC", r, 0, 0);	// LDW  *++SP,r
1327
}
1328
 
1329
void C67_POP_DW(int r)
1330
{
1331
    C67_asm("LDDW.D SP PRE INC", r, 0, 0);	// LDDW  *++SP,r
1332
}
1333
 
1334
void C67_CMPLT(int s1, int s2, int dst)
1335
{
1336
    C67_asm("CMPLT.L1", s1, s2, dst);
1337
}
1338
 
1339
void C67_CMPGT(int s1, int s2, int dst)
1340
{
1341
    C67_asm("CMPGT.L1", s1, s2, dst);
1342
}
1343
 
1344
void C67_CMPEQ(int s1, int s2, int dst)
1345
{
1346
    C67_asm("CMPEQ.L1", s1, s2, dst);
1347
}
1348
 
1349
void C67_CMPLTU(int s1, int s2, int dst)
1350
{
1351
    C67_asm("CMPLTU.L1", s1, s2, dst);
1352
}
1353
 
1354
void C67_CMPGTU(int s1, int s2, int dst)
1355
{
1356
    C67_asm("CMPGTU.L1", s1, s2, dst);
1357
}
1358
 
1359
 
1360
void C67_CMPLTSP(int s1, int s2, int dst)
1361
{
1362
    C67_asm("CMPLTSP.S1", s1, s2, dst);
1363
}
1364
 
1365
void C67_CMPGTSP(int s1, int s2, int dst)
1366
{
1367
    C67_asm("CMPGTSP.S1", s1, s2, dst);
1368
}
1369
 
1370
void C67_CMPEQSP(int s1, int s2, int dst)
1371
{
1372
    C67_asm("CMPEQSP.S1", s1, s2, dst);
1373
}
1374
 
1375
void C67_CMPLTDP(int s1, int s2, int dst)
1376
{
1377
    C67_asm("CMPLTDP.S1", s1, s2, dst);
1378
}
1379
 
1380
void C67_CMPGTDP(int s1, int s2, int dst)
1381
{
1382
    C67_asm("CMPGTDP.S1", s1, s2, dst);
1383
}
1384
 
1385
void C67_CMPEQDP(int s1, int s2, int dst)
1386
{
1387
    C67_asm("CMPEQDP.S1", s1, s2, dst);
1388
}
1389
 
1390
 
1391
void C67_IREG_B_REG(int inv, int r1, int r2)	// [!R] B  r2
1392
{
1393
    C67_asm("B.S2", inv, r1, r2);
1394
}
1395
 
1396
 
1397
// call with how many 32 bit words to skip
1398
// (0 would branch to the branch instruction)
1399
 
1400
void C67_B_DISP(int disp)	//  B  +2  Branch with constant displacement
1401
{
1402
    // Branch point is relative to the 8 word fetch packet
1403
    //
1404
    // we will assume the text section always starts on an 8 word (32 byte boundary)
1405
    //
1406
    // so add in how many words into the fetch packet the branch is
1407
 
1408
 
1409
    C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1410
}
1411
 
1412
void C67_NOP(int n)
1413
{
1414
    C67_asm("NOP", n, 0, 0);
1415
}
1416
 
1417
void C67_ADDK(int n, int r)
1418
{
1419
    ALWAYS_ASSERT(abs(n) < 32767);
1420
 
1421
    C67_asm("ADDK", n, r, 0);
1422
}
1423
 
1424
void C67_ADDK_PARALLEL(int n, int r)
1425
{
1426
    ALWAYS_ASSERT(abs(n) < 32767);
1427
 
1428
    C67_asm("||ADDK", n, r, 0);
1429
}
1430
 
1431
void C67_Adjust_ADDK(int *inst, int n)
1432
{
1433
    ALWAYS_ASSERT(abs(n) < 32767);
1434
 
1435
    *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1436
}
1437
 
1438
void C67_MV(int r, int v)
1439
{
1440
    C67_asm("MV.L", 0, r, v);
1441
}
1442
 
1443
 
1444
void C67_DPTRUNC(int r, int v)
1445
{
1446
    C67_asm("DPTRUNC.L", 0, r, v);
1447
}
1448
 
1449
void C67_SPTRUNC(int r, int v)
1450
{
1451
    C67_asm("SPTRUNC.L", 0, r, v);
1452
}
1453
 
1454
void C67_INTSP(int r, int v)
1455
{
1456
    C67_asm("INTSP.L", 0, r, v);
1457
}
1458
 
1459
void C67_INTDP(int r, int v)
1460
{
1461
    C67_asm("INTDP.L", 0, r, v);
1462
}
1463
 
1464
void C67_INTSPU(int r, int v)
1465
{
1466
    C67_asm("INTSPU.L", 0, r, v);
1467
}
1468
 
1469
void C67_INTDPU(int r, int v)
1470
{
1471
    C67_asm("INTDPU.L", 0, r, v);
1472
}
1473
 
1474
void C67_SPDP(int r, int v)
1475
{
1476
    C67_asm("SPDP.L", 0, r, v);
1477
}
1478
 
1479
void C67_DPSP(int r, int v)	// note regs must be on the same side
1480
{
1481
    C67_asm("DPSP.L", 0, r, v);
1482
}
1483
 
1484
void C67_ADD(int r, int v)
1485
{
1486
    C67_asm("ADD.L", v, r, v);
1487
}
1488
 
1489
void C67_SUB(int r, int v)
1490
{
1491
    C67_asm("SUB.L", v, r, v);
1492
}
1493
 
1494
void C67_AND(int r, int v)
1495
{
1496
    C67_asm("AND.L", v, r, v);
1497
}
1498
 
1499
void C67_OR(int r, int v)
1500
{
1501
    C67_asm("OR.L", v, r, v);
1502
}
1503
 
1504
void C67_XOR(int r, int v)
1505
{
1506
    C67_asm("XOR.L", v, r, v);
1507
}
1508
 
1509
void C67_ADDSP(int r, int v)
1510
{
1511
    C67_asm("ADDSP.L", v, r, v);
1512
}
1513
 
1514
void C67_SUBSP(int r, int v)
1515
{
1516
    C67_asm("SUBSP.L", v, r, v);
1517
}
1518
 
1519
void C67_MPYSP(int r, int v)
1520
{
1521
    C67_asm("MPYSP.M", v, r, v);
1522
}
1523
 
1524
void C67_ADDDP(int r, int v)
1525
{
1526
    C67_asm("ADDDP.L", v, r, v);
1527
}
1528
 
1529
void C67_SUBDP(int r, int v)
1530
{
1531
    C67_asm("SUBDP.L", v, r, v);
1532
}
1533
 
1534
void C67_MPYDP(int r, int v)
1535
{
1536
    C67_asm("MPYDP.M", v, r, v);
1537
}
1538
 
1539
void C67_MPYI(int r, int v)
1540
{
1541
    C67_asm("MPYI.M", v, r, v);
1542
}
1543
 
1544
void C67_SHL(int r, int v)
1545
{
1546
    C67_asm("SHL.S", r, v, v);
1547
}
1548
 
1549
void C67_SHRU(int r, int v)
1550
{
1551
    C67_asm("SHRU.S", r, v, v);
1552
}
1553
 
1554
void C67_SHR(int r, int v)
1555
{
1556
    C67_asm("SHR.S", r, v, v);
1557
}
1558
 
1559
 
1560
 
1561
/* load 'r' from value 'sv' */
1562
void load(int r, SValue * sv)
1563
{
1564
    int v, t, ft, fc, fr, size = 0, element;
6429 siemargl 1565
    BOOL Unsigned = FALSE;
145 halyavin 1566
    SValue v1;
1567
 
1568
    fr = sv->r;
1569
    ft = sv->type.t;
6429 siemargl 1570
    fc = sv->c.i;
145 halyavin 1571
 
1572
    v = fr & VT_VALMASK;
1573
    if (fr & VT_LVAL) {
1574
	if (v == VT_LLOCAL) {
1575
	    v1.type.t = VT_INT;
1576
	    v1.r = VT_LOCAL | VT_LVAL;
6429 siemargl 1577
	    v1.c.i = fc;
145 halyavin 1578
	    load(r, &v1);
1579
	    fr = r;
1580
	} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
6429 siemargl 1581
	    tcc_error("long double not supported");
145 halyavin 1582
	} else if ((ft & VT_TYPE) == VT_BYTE) {
1583
	    size = 1;
1584
	} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1585
	    size = 1;
1586
	    Unsigned = TRUE;
1587
	} else if ((ft & VT_TYPE) == VT_SHORT) {
1588
	    size = 2;
1589
	} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1590
	    size = 2;
1591
	    Unsigned = TRUE;
1592
	} else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1593
	    size = 8;
1594
	} else {
1595
	    size = 4;
1596
	}
1597
 
1598
	// check if fc is a positive reference on the stack,
1599
	// if it is tcc is referencing what it thinks is a parameter
1600
	// on the stack, so check if it is really in a register.
1601
 
1602
 
1603
	if (v == VT_LOCAL && fc > 0) {
1604
	    int stack_pos = 8;
1605
 
1606
	    for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1607
		if (fc == stack_pos)
1608
		    break;
1609
 
1610
		stack_pos += TranslateStackToReg[t];
1611
	    }
1612
 
1613
	    // param has been pushed on stack, get it like a local var
1614
 
1615
	    fc = ParamLocOnStack[t] - 8;
1616
	}
1617
 
1618
	if ((fr & VT_VALMASK) < VT_CONST)	// check for pure indirect
1619
	{
1620
	    if (size == 1) {
1621
		if (Unsigned)
1622
		    C67_LDBU_PTR(v, r);	// LDBU  *v,r
1623
		else
1624
		    C67_LDB_PTR(v, r);	// LDB  *v,r
1625
	    } else if (size == 2) {
1626
		if (Unsigned)
1627
		    C67_LDHU_PTR(v, r);	// LDHU  *v,r
1628
		else
1629
		    C67_LDH_PTR(v, r);	// LDH  *v,r
1630
	    } else if (size == 4) {
1631
		C67_LDW_PTR(v, r);	// LDW  *v,r
1632
	    } else if (size == 8) {
1633
		C67_LDDW_PTR(v, r);	// LDDW  *v,r
1634
	    }
1635
 
1636
	    C67_NOP(4);		// NOP 4
1637
	    return;
1638
	} else if (fr & VT_SYM) {
1639
	    greloc(cur_text_section, sv->sym, ind, R_C60LO16);	// rem the inst need to be patched
1640
	    greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1641
 
1642
 
1643
	    C67_MVKL(C67_A0, fc);	//r=reg to load,  constant
1644
	    C67_MVKH(C67_A0, fc);	//r=reg to load,  constant
1645
 
1646
 
1647
	    if (size == 1) {
1648
		if (Unsigned)
1649
		    C67_LDBU_PTR(C67_A0, r);	// LDBU  *A0,r
1650
		else
1651
		    C67_LDB_PTR(C67_A0, r);	// LDB  *A0,r
1652
	    } else if (size == 2) {
1653
		if (Unsigned)
1654
		    C67_LDHU_PTR(C67_A0, r);	// LDHU  *A0,r
1655
		else
1656
		    C67_LDH_PTR(C67_A0, r);	// LDH  *A0,r
1657
	    } else if (size == 4) {
1658
		C67_LDW_PTR(C67_A0, r);	// LDW  *A0,r
1659
	    } else if (size == 8) {
1660
		C67_LDDW_PTR(C67_A0, r);	// LDDW  *A0,r
1661
	    }
1662
 
1663
	    C67_NOP(4);		// NOP 4
1664
	    return;
1665
	} else {
1666
	    element = size;
1667
 
1668
	    // divide offset in bytes to create element index
1669
	    C67_MVKL(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
1670
	    C67_MVKH(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
1671
 
1672
	    if (size == 1) {
1673
		if (Unsigned)
1674
		    C67_LDBU_SP_A0(r);	// LDBU  r, SP[A0]
1675
		else
1676
		    C67_LDB_SP_A0(r);	// LDB  r, SP[A0]
1677
	    } else if (size == 2) {
1678
		if (Unsigned)
1679
		    C67_LDHU_SP_A0(r);	// LDHU  r, SP[A0]
1680
		else
1681
		    C67_LDH_SP_A0(r);	// LDH  r, SP[A0]
1682
	    } else if (size == 4) {
1683
		C67_LDW_SP_A0(r);	// LDW  r, SP[A0]
1684
	    } else if (size == 8) {
1685
		C67_LDDW_SP_A0(r);	// LDDW  r, SP[A0]
1686
	    }
1687
 
1688
 
1689
	    C67_NOP(4);		// NOP 4
1690
	    return;
1691
	}
1692
    } else {
1693
	if (v == VT_CONST) {
1694
	    if (fr & VT_SYM) {
1695
		greloc(cur_text_section, sv->sym, ind, R_C60LO16);	// rem the inst need to be patched
1696
		greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1697
	    }
1698
	    C67_MVKL(r, fc);	//r=reg to load, constant
1699
	    C67_MVKH(r, fc);	//r=reg to load, constant
1700
	} else if (v == VT_LOCAL) {
1701
	    C67_MVKL(r, fc + 8);	//r=reg to load, constant C67 stack points to next free
1702
	    C67_MVKH(r, fc + 8);	//r=reg to load, constant
1703
	    C67_ADD(C67_FP, r);	// MV v,r   v -> r
1704
	} else if (v == VT_CMP) {
1705
	    C67_MV(C67_compare_reg, r);	// MV v,r   v -> r
1706
	} else if (v == VT_JMP || v == VT_JMPI) {
1707
	    t = v & 1;
1708
	    C67_B_DISP(4);	//  Branch with constant displacement, skip over this branch, load, nop, load
1709
	    C67_MVKL(r, t);	//  r=reg to load, 0 or 1 (do this while branching)
1710
	    C67_NOP(4);		//  NOP 4
1711
	    gsym(fc);		//  modifies other branches to branch here
1712
	    C67_MVKL(r, t ^ 1);	//  r=reg to load, 0 or 1
1713
	} else if (v != r) {
1714
	    C67_MV(v, r);	// MV v,r   v -> r
1715
 
1716
	    if ((ft & VT_BTYPE) == VT_DOUBLE)
1717
		C67_MV(v + 1, r + 1);	// MV v,r   v -> r
1718
	}
1719
    }
1720
}
1721
 
1722
 
1723
/* store register 'r' in lvalue 'v' */
1724
void store(int r, SValue * v)
1725
{
1726
    int fr, bt, ft, fc, size, t, element;
1727
 
1728
    ft = v->type.t;
6429 siemargl 1729
    fc = v->c.i;
145 halyavin 1730
    fr = v->r & VT_VALMASK;
1731
    bt = ft & VT_BTYPE;
1732
    /* XXX: incorrect if float reg to reg */
1733
 
1734
    if (bt == VT_LDOUBLE) {
6429 siemargl 1735
	tcc_error("long double not supported");
145 halyavin 1736
    } else {
1737
	if (bt == VT_SHORT)
1738
	    size = 2;
1739
	else if (bt == VT_BYTE)
1740
	    size = 1;
1741
	else if (bt == VT_DOUBLE)
1742
	    size = 8;
1743
	else
1744
	    size = 4;
1745
 
1746
	if ((v->r & VT_VALMASK) == VT_CONST) {
1747
	    /* constant memory reference */
1748
 
1749
	    if (v->r & VT_SYM) {
1750
		greloc(cur_text_section, v->sym, ind, R_C60LO16);	// rem the inst need to be patched
1751
		greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
1752
	    }
1753
	    C67_MVKL(C67_A0, fc);	//r=reg to load,  constant
1754
	    C67_MVKH(C67_A0, fc);	//r=reg to load,  constant
1755
 
1756
	    if (size == 1)
1757
		C67_STB_PTR(r, C67_A0);	// STB  r, *A0
1758
	    else if (size == 2)
1759
		C67_STH_PTR(r, C67_A0);	// STH  r, *A0
1760
	    else if (size == 4 || size == 8)
1761
		C67_STW_PTR(r, C67_A0);	// STW  r, *A0
1762
 
1763
	    if (size == 8)
1764
		C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1);	// STW  r, *+A0[1]
1765
	} else if ((v->r & VT_VALMASK) == VT_LOCAL) {
1766
	    // check case of storing to passed argument that
1767
	    // tcc thinks is on the stack but for C67 is
1768
	    // passed as a reg.  However it may have been
1769
	    // saved to the stack, if that reg was required
1770
	    // for a call to a child function
1771
 
1772
	    if (fc > 0)		// argument ??
1773
	    {
1774
		// walk through sizes and figure which param
1775
 
1776
		int stack_pos = 8;
1777
 
1778
		for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1779
		    if (fc == stack_pos)
1780
			break;
1781
 
1782
		    stack_pos += TranslateStackToReg[t];
1783
		}
1784
 
1785
		// param has been pushed on stack, get it like a local var
1786
		fc = ParamLocOnStack[t] - 8;
1787
	    }
1788
 
1789
	    if (size == 8)
1790
		element = 4;
1791
	    else
1792
		element = size;
1793
 
1794
	    // divide offset in bytes to create word index
1795
	    C67_MVKL(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
1796
	    C67_MVKH(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
1797
 
1798
 
1799
 
1800
	    if (size == 1)
1801
		C67_STB_SP_A0(r);	// STB  r, SP[A0]
1802
	    else if (size == 2)
1803
		C67_STH_SP_A0(r);	// STH  r, SP[A0]
1804
	    else if (size == 4 || size == 8)
1805
		C67_STW_SP_A0(r);	// STW  r, SP[A0]
1806
 
1807
	    if (size == 8) {
1808
		C67_ADDK(1, C67_A0);	//  ADDK 1,A0
1809
		C67_STW_SP_A0(r + 1);	//  STW  r, SP[A0]
1810
	    }
1811
	} else {
1812
	    if (size == 1)
1813
		C67_STB_PTR(r, fr);	// STB  r, *fr
1814
	    else if (size == 2)
1815
		C67_STH_PTR(r, fr);	// STH  r, *fr
1816
	    else if (size == 4 || size == 8)
1817
		C67_STW_PTR(r, fr);	// STW  r, *fr
1818
 
1819
	    if (size == 8) {
1820
		C67_STW_PTR_PRE_INC(r + 1, fr, 1);	// STW  r, *+fr[1]
1821
	    }
1822
	}
1823
    }
1824
}
1825
 
1826
/* 'is_jmp' is '1' if it is a jump */
1827
static void gcall_or_jmp(int is_jmp)
1828
{
1829
    int r;
1830
    Sym *sym;
1831
 
1832
    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1833
	/* constant case */
1834
	if (vtop->r & VT_SYM) {
1835
	    /* relocation case */
1836
 
1837
	    // get add into A0, then start the jump B3
1838
 
1839
	    greloc(cur_text_section, vtop->sym, ind, R_C60LO16);	// rem the inst need to be patched
1840
	    greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
1841
 
1842
	    C67_MVKL(C67_A0, 0);	//r=reg to load, constant
1843
	    C67_MVKH(C67_A0, 0);	//r=reg to load, constant
1844
	    C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	//  B.S2x  A0
1845
 
1846
	    if (is_jmp) {
1847
		C67_NOP(5);	// simple jump, just put NOP
1848
	    } else {
1849
		// Call, must load return address into B3 during delay slots
1850
 
1851
		sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address
1852
		greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched
1853
		greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1854
		C67_MVKL(C67_B3, 0);	//r=reg to load, constant
1855
		C67_MVKH(C67_B3, 0);	//r=reg to load, constant
1856
		C67_NOP(3);	// put remaining NOPs
1857
	    }
1858
	} else {
1859
	    /* put an empty PC32 relocation */
1860
	    ALWAYS_ASSERT(FALSE);
1861
	}
1862
    } else {
1863
	/* otherwise, indirect call */
1864
	r = gv(RC_INT);
1865
	C67_IREG_B_REG(0, C67_CREG_ZERO, r);	//  B.S2x  r
1866
 
1867
	if (is_jmp) {
1868
	    C67_NOP(5);		// simple jump, just put NOP
1869
	} else {
1870
	    // Call, must load return address into B3 during delay slots
1871
 
1872
	    sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address
1873
	    greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched
1874
	    greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1875
	    C67_MVKL(C67_B3, 0);	//r=reg to load, constant
1876
	    C67_MVKH(C67_B3, 0);	//r=reg to load, constant
1877
	    C67_NOP(3);		// put remaining NOPs
1878
	}
1879
    }
1880
}
1881
 
6429 siemargl 1882
/* Return the number of registers needed to return the struct, or 0 if
1883
   returning via struct pointer. */
1884
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
1885
    *ret_align = 1; // Never have to re-align return values for x86-64
1886
    return 0;
1887
}
1888
 
145 halyavin 1889
/* generate function call with address in (vtop->t, vtop->c) and free function
1890
   context. Stack entry is popped */
1891
void gfunc_call(int nb_args)
1892
{
1893
    int i, r, size = 0;
1894
    int args_sizes[NoCallArgsPassedOnStack];
1895
 
1896
    if (nb_args > NoCallArgsPassedOnStack) {
6429 siemargl 1897
	tcc_error("more than 10 function params not currently supported");
145 halyavin 1898
	// handle more than 10, put some on the stack
1899
    }
1900
 
1901
    for (i = 0; i < nb_args; i++) {
1902
	if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1903
	    ALWAYS_ASSERT(FALSE);
1904
	} else {
1905
	    /* simple type (currently always same size) */
1906
	    /* XXX: implicit cast ? */
1907
 
1908
 
1909
	    if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
6429 siemargl 1910
		tcc_error("long long not supported");
145 halyavin 1911
	    } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
6429 siemargl 1912
		tcc_error("long double not supported");
145 halyavin 1913
	    } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1914
		size = 8;
1915
	    } else {
1916
		size = 4;
1917
	    }
1918
 
1919
	    // put the parameter into the corresponding reg (pair)
1920
 
1921
	    r = gv(RC_C67_A4 << (2 * i));
1922
 
1923
	    // must put on stack because with 1 pass compiler , no way to tell
1924
	    // if an up coming nested call might overwrite these regs
1925
 
1926
	    C67_PUSH(r);
1927
 
1928
	    if (size == 8) {
1929
		C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3);	// STW  r, *+SP[3] (go back and put the other)
1930
	    }
1931
	    args_sizes[i] = size;
1932
	}
1933
	vtop--;
1934
    }
1935
    // POP all the params on the stack into registers for the
1936
    // immediate call (in reverse order)
1937
 
1938
    for (i = nb_args - 1; i >= 0; i--) {
1939
 
1940
	if (args_sizes[i] == 8)
1941
	    C67_POP_DW(TREG_C67_A4 + i * 2);
1942
	else
1943
	    C67_POP(TREG_C67_A4 + i * 2);
1944
    }
1945
    gcall_or_jmp(0);
1946
    vtop--;
1947
}
1948
 
1949
 
1950
// to be compatible with Code Composer for the C67
1951
// the first 10 parameters must be passed in registers
1952
// (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1953
// ending with B12:B13.
1954
//
1955
// When a call is made, if the caller has its parameters
1956
// in regs A4-B13 these must be saved before/as the call
1957
// parameters are loaded and restored upon return (or if/when needed).
1958
 
1959
/* generate function prolog of type 't' */
1960
void gfunc_prolog(CType * func_type)
1961
{
1962
    int addr, align, size, func_call, i;
1963
    Sym *sym;
1964
    CType *type;
1965
 
1966
    sym = func_type->ref;
1967
    func_call = sym->r;
1968
    addr = 8;
1969
    /* if the function returns a structure, then add an
1970
       implicit pointer parameter */
1971
    func_vt = sym->type;
6429 siemargl 1972
    func_var = (sym->c == FUNC_ELLIPSIS);
145 halyavin 1973
    if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1974
	func_vc = addr;
1975
	addr += 4;
1976
    }
1977
 
1978
    NoOfCurFuncArgs = 0;
1979
 
1980
    /* define parameters */
1981
    while ((sym = sym->next) != NULL) {
1982
	type = &sym->type;
6429 siemargl 1983
	sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
145 halyavin 1984
	size = type_size(type, &align);
1985
	size = (size + 3) & ~3;
1986
 
1987
	// keep track of size of arguments so
1988
	// we can translate where tcc thinks they
1989
	// are on the stack into the appropriate reg
1990
 
1991
	TranslateStackToReg[NoOfCurFuncArgs] = size;
1992
	NoOfCurFuncArgs++;
1993
 
1994
#ifdef FUNC_STRUCT_PARAM_AS_PTR
1995
	/* structs are passed as pointer */
1996
	if ((type->t & VT_BTYPE) == VT_STRUCT) {
1997
	    size = 4;
1998
	}
1999
#endif
2000
	addr += size;
2001
    }
2002
    func_ret_sub = 0;
2003
    /* pascal type call ? */
2004
    if (func_call == FUNC_STDCALL)
2005
	func_ret_sub = addr - 8;
2006
 
2007
    C67_MV(C67_FP, C67_A0);	//  move FP -> A0
2008
    C67_MV(C67_SP, C67_FP);	//  move SP -> FP
2009
 
2010
    // place all the args passed in regs onto the stack
2011
 
2012
    loc = 0;
2013
    for (i = 0; i < NoOfCurFuncArgs; i++) {
2014
 
2015
	ParamLocOnStack[i] = loc;	// remember where the param is
2016
	loc += -8;
2017
 
2018
	C67_PUSH(TREG_C67_A4 + i * 2);
2019
 
2020
	if (TranslateStackToReg[i] == 8) {
2021
	    C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3);	// STW  r, *+SP[1] (go back and put the other)
2022
	}
2023
    }
2024
 
2025
    TotalBytesPushedOnStack = -loc;
2026
 
2027
    func_sub_sp_offset = ind;	// remember where we put the stack instruction
2028
    C67_ADDK(0, C67_SP);	//  ADDK.L2 loc,SP  (just put zero temporarily)
2029
 
2030
    C67_PUSH(C67_A0);
2031
    C67_PUSH(C67_B3);
2032
}
2033
 
2034
/* generate function epilog */
2035
void gfunc_epilog(void)
2036
{
2037
    {
2038
	int local = (-loc + 7) & -8;	// stack must stay aligned to 8 bytes for LDDW instr
2039
	C67_POP(C67_B3);
2040
	C67_NOP(4);		// NOP wait for load
2041
	C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3);	//  B.S2  B3
2042
	C67_POP(C67_FP);
2043
	C67_ADDK(local, C67_SP);	//  ADDK.L2 loc,SP
2044
	C67_Adjust_ADDK((int *) (cur_text_section->data +
2045
				 func_sub_sp_offset),
2046
			-local + TotalBytesPushedOnStack);
2047
	C67_NOP(3);		// NOP
2048
    }
2049
}
2050
 
2051
/* generate a jump to a label */
2052
int gjmp(int t)
2053
{
2054
    int ind1 = ind;
2055
 
2056
    C67_MVKL(C67_A0, t);	//r=reg to load,  constant
2057
    C67_MVKH(C67_A0, t);	//r=reg to load,  constant
2058
    C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	// [!R] B.S2x  A0
2059
    C67_NOP(5);
2060
    return ind1;
2061
}
2062
 
2063
/* generate a jump to a fixed address */
2064
void gjmp_addr(int a)
2065
{
2066
    Sym *sym;
2067
    // I guess this routine is used for relative short
2068
    // local jumps, for now just handle it as the general
2069
    // case
2070
 
2071
    // define a label that will be relocated
2072
 
2073
    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
2074
    greloc(cur_text_section, sym, ind, R_C60LO16);
2075
    greloc(cur_text_section, sym, ind + 4, R_C60HI16);
2076
 
2077
    gjmp(0);			// place a zero there later the symbol will be added to it
2078
}
2079
 
2080
/* generate a test. set 'inv' to invert test. Stack entry is popped */
2081
int gtst(int inv, int t)
2082
{
2083
    int ind1, n;
2084
    int v, *p;
2085
 
2086
    v = vtop->r & VT_VALMASK;
2087
    if (v == VT_CMP) {
2088
	/* fast case : can jump directly since flags are set */
2089
	// C67 uses B2 sort of as flags register
2090
	ind1 = ind;
2091
	C67_MVKL(C67_A0, t);	//r=reg to load, constant
2092
	C67_MVKH(C67_A0, t);	//r=reg to load, constant
2093
 
2094
	if (C67_compare_reg != TREG_EAX &&	// check if not already in a conditional test reg
2095
	    C67_compare_reg != TREG_EDX &&
2096
	    C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
2097
	    C67_MV(C67_compare_reg, C67_B2);
2098
	    C67_compare_reg = C67_B2;
2099
	}
2100
 
2101
	C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0);	// [!R] B.S2x  A0
2102
	C67_NOP(5);
2103
	t = ind1;		//return where we need to patch
2104
 
2105
    } else if (v == VT_JMP || v == VT_JMPI) {
2106
	/* && or || optimization */
2107
	if ((v & 1) == inv) {
2108
	    /* insert vtop->c jump list in t */
2109
 
2110
	    // I guess the idea is to traverse to the
2111
	    // null at the end of the list and store t
2112
	    // there
2113
 
6429 siemargl 2114
	    n = vtop->c.i;
145 halyavin 2115
	    while (n != 0) {
2116
		p = (int *) (cur_text_section->data + n);
2117
 
2118
		// extract 32 bit address from MVKH/MVKL
2119
		n = ((*p >> 7) & 0xffff);
2120
		n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2121
	    }
2122
	    *p |= (t & 0xffff) << 7;
2123
	    *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2124
	    t = vtop->c.i;
2125
 
2126
	} else {
2127
	    t = gjmp(t);
2128
	    gsym(vtop->c.i);
2129
	}
2130
    }
2131
    vtop--;
2132
    return t;
2133
}
2134
 
2135
/* generate an integer binary operation */
2136
void gen_opi(int op)
2137
{
2138
    int r, fr, opc, t;
2139
 
2140
    switch (op) {
2141
    case '+':
2142
    case TOK_ADDC1:		/* add with carry generation */
2143
	opc = 0;
2144
      gen_op8:
2145
 
2146
 
2147
// C67 can't do const compares, must load into a reg
2148
// so just go to gv2 directly - tktk
2149
 
2150
 
2151
 
2152
	if (op >= TOK_ULT && op <= TOK_GT)
2153
	    gv2(RC_INT_BSIDE, RC_INT);	// make sure r (src1) is on the B Side of CPU
2154
	else
2155
	    gv2(RC_INT, RC_INT);
2156
 
2157
	r = vtop[-1].r;
2158
	fr = vtop[0].r;
2159
 
2160
	C67_compare_reg = C67_B2;
2161
 
2162
 
2163
	if (op == TOK_LT) {
2164
	    C67_CMPLT(r, fr, C67_B2);
6429 siemargl 2165
	    C67_invert_test = FALSE;
145 halyavin 2166
	} else if (op == TOK_GE) {
2167
	    C67_CMPLT(r, fr, C67_B2);
6429 siemargl 2168
	    C67_invert_test = TRUE;
145 halyavin 2169
	} else if (op == TOK_GT) {
2170
	    C67_CMPGT(r, fr, C67_B2);
6429 siemargl 2171
	    C67_invert_test = FALSE;
145 halyavin 2172
	} else if (op == TOK_LE) {
2173
	    C67_CMPGT(r, fr, C67_B2);
6429 siemargl 2174
	    C67_invert_test = TRUE;
145 halyavin 2175
	} else if (op == TOK_EQ) {
2176
	    C67_CMPEQ(r, fr, C67_B2);
6429 siemargl 2177
	    C67_invert_test = FALSE;
145 halyavin 2178
	} else if (op == TOK_NE) {
2179
	    C67_CMPEQ(r, fr, C67_B2);
6429 siemargl 2180
	    C67_invert_test = TRUE;
145 halyavin 2181
	} else if (op == TOK_ULT) {
2182
	    C67_CMPLTU(r, fr, C67_B2);
6429 siemargl 2183
	    C67_invert_test = FALSE;
145 halyavin 2184
	} else if (op == TOK_UGE) {
2185
	    C67_CMPLTU(r, fr, C67_B2);
6429 siemargl 2186
	    C67_invert_test = TRUE;
145 halyavin 2187
	} else if (op == TOK_UGT) {
2188
	    C67_CMPGTU(r, fr, C67_B2);
6429 siemargl 2189
	    C67_invert_test = FALSE;
145 halyavin 2190
	} else if (op == TOK_ULE) {
2191
	    C67_CMPGTU(r, fr, C67_B2);
6429 siemargl 2192
	    C67_invert_test = TRUE;
145 halyavin 2193
	} else if (op == '+')
2194
	    C67_ADD(fr, r);	// ADD  r,fr,r
2195
	else if (op == '-')
2196
	    C67_SUB(fr, r);	// SUB  r,fr,r
2197
	else if (op == '&')
2198
	    C67_AND(fr, r);	// AND  r,fr,r
2199
	else if (op == '|')
2200
	    C67_OR(fr, r);	// OR  r,fr,r
2201
	else if (op == '^')
2202
	    C67_XOR(fr, r);	// XOR  r,fr,r
2203
	else
2204
	    ALWAYS_ASSERT(FALSE);
2205
 
2206
	vtop--;
2207
	if (op >= TOK_ULT && op <= TOK_GT) {
2208
	    vtop->r = VT_CMP;
2209
	    vtop->c.i = op;
2210
	}
2211
	break;
2212
    case '-':
2213
    case TOK_SUBC1:		/* sub with carry generation */
2214
	opc = 5;
2215
	goto gen_op8;
2216
    case TOK_ADDC2:		/* add with carry use */
2217
	opc = 2;
2218
	goto gen_op8;
2219
    case TOK_SUBC2:		/* sub with carry use */
2220
	opc = 3;
2221
	goto gen_op8;
2222
    case '&':
2223
	opc = 4;
2224
	goto gen_op8;
2225
    case '^':
2226
	opc = 6;
2227
	goto gen_op8;
2228
    case '|':
2229
	opc = 1;
2230
	goto gen_op8;
2231
    case '*':
2232
    case TOK_UMULL:
2233
	gv2(RC_INT, RC_INT);
2234
	r = vtop[-1].r;
2235
	fr = vtop[0].r;
2236
	vtop--;
2237
	C67_MPYI(fr, r);	// 32 bit bultiply  fr,r,fr
2238
	C67_NOP(8);		// NOP 8 for worst case
2239
	break;
2240
    case TOK_SHL:
2241
	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
2242
	r = vtop[-1].r;
2243
	fr = vtop[0].r;
2244
	vtop--;
2245
	C67_SHL(fr, r);		// arithmetic/logical shift
2246
	break;
2247
 
2248
    case TOK_SHR:
2249
	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
2250
	r = vtop[-1].r;
2251
	fr = vtop[0].r;
2252
	vtop--;
2253
	C67_SHRU(fr, r);	// logical shift
2254
	break;
2255
 
2256
    case TOK_SAR:
2257
	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
2258
	r = vtop[-1].r;
2259
	fr = vtop[0].r;
2260
	vtop--;
2261
	C67_SHR(fr, r);		// arithmetic shift
2262
	break;
2263
 
2264
    case '/':
2265
	t = TOK__divi;
2266
      call_func:
2267
	vswap();
2268
	/* call generic idiv function */
2269
	vpush_global_sym(&func_old_type, t);
2270
	vrott(3);
2271
	gfunc_call(2);
2272
	vpushi(0);
2273
	vtop->r = REG_IRET;
2274
	vtop->r2 = VT_CONST;
2275
	break;
2276
    case TOK_UDIV:
2277
    case TOK_PDIV:
2278
	t = TOK__divu;
2279
	goto call_func;
2280
    case '%':
2281
	t = TOK__remi;
2282
	goto call_func;
2283
    case TOK_UMOD:
2284
	t = TOK__remu;
2285
	goto call_func;
2286
 
2287
    default:
2288
	opc = 7;
2289
	goto gen_op8;
2290
    }
2291
}
2292
 
2293
/* generate a floating point operation 'v = t1 op t2' instruction. The
2294
   two operands are guaranted to have the same floating point type */
2295
/* XXX: need to use ST1 too */
2296
void gen_opf(int op)
2297
{
2298
    int ft, fc, fr, r;
2299
 
2300
    if (op >= TOK_ULT && op <= TOK_GT)
2301
	gv2(RC_EDX, RC_EAX);	// make sure src2 is on b side
2302
    else
2303
	gv2(RC_FLOAT, RC_FLOAT);	// make sure src2 is on b side
2304
 
2305
    ft = vtop->type.t;
6429 siemargl 2306
    fc = vtop->c.i;
145 halyavin 2307
    r = vtop->r;
2308
    fr = vtop[-1].r;
2309
 
2310
 
2311
    if ((ft & VT_BTYPE) == VT_LDOUBLE)
6429 siemargl 2312
	tcc_error("long doubles not supported");
145 halyavin 2313
 
2314
    if (op >= TOK_ULT && op <= TOK_GT) {
2315
 
2316
	r = vtop[-1].r;
2317
	fr = vtop[0].r;
2318
 
2319
	C67_compare_reg = C67_B2;
2320
 
2321
	if (op == TOK_LT) {
2322
	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2323
		C67_CMPLTDP(r, fr, C67_B2);
2324
	    else
2325
		C67_CMPLTSP(r, fr, C67_B2);
2326
 
6429 siemargl 2327
	    C67_invert_test = FALSE;
145 halyavin 2328
	} else if (op == TOK_GE) {
2329
	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2330
		C67_CMPLTDP(r, fr, C67_B2);
2331
	    else
2332
		C67_CMPLTSP(r, fr, C67_B2);
2333
 
6429 siemargl 2334
	    C67_invert_test = TRUE;
145 halyavin 2335
	} else if (op == TOK_GT) {
2336
	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2337
		C67_CMPGTDP(r, fr, C67_B2);
2338
	    else
2339
		C67_CMPGTSP(r, fr, C67_B2);
2340
 
6429 siemargl 2341
	    C67_invert_test = FALSE;
145 halyavin 2342
	} else if (op == TOK_LE) {
2343
	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2344
		C67_CMPGTDP(r, fr, C67_B2);
2345
	    else
2346
		C67_CMPGTSP(r, fr, C67_B2);
2347
 
6429 siemargl 2348
	    C67_invert_test = TRUE;
145 halyavin 2349
	} else if (op == TOK_EQ) {
2350
	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2351
		C67_CMPEQDP(r, fr, C67_B2);
2352
	    else
2353
		C67_CMPEQSP(r, fr, C67_B2);
2354
 
6429 siemargl 2355
	    C67_invert_test = FALSE;
145 halyavin 2356
	} else if (op == TOK_NE) {
2357
	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2358
		C67_CMPEQDP(r, fr, C67_B2);
2359
	    else
2360
		C67_CMPEQSP(r, fr, C67_B2);
2361
 
6429 siemargl 2362
	    C67_invert_test = TRUE;
145 halyavin 2363
	} else {
2364
	    ALWAYS_ASSERT(FALSE);
2365
	}
2366
	vtop->r = VT_CMP;	// tell TCC that result is in "flags" actually B2
2367
    } else {
2368
	if (op == '+') {
2369
	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
2370
		C67_ADDDP(r, fr);	// ADD  fr,r,fr
2371
		C67_NOP(6);
2372
	    } else {
2373
		C67_ADDSP(r, fr);	// ADD  fr,r,fr
2374
		C67_NOP(3);
2375
	    }
2376
	    vtop--;
2377
	} else if (op == '-') {
2378
	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
2379
		C67_SUBDP(r, fr);	// SUB  fr,r,fr
2380
		C67_NOP(6);
2381
	    } else {
2382
		C67_SUBSP(r, fr);	// SUB  fr,r,fr
2383
		C67_NOP(3);
2384
	    }
2385
	    vtop--;
2386
	} else if (op == '*') {
2387
	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
2388
		C67_MPYDP(r, fr);	// MPY  fr,r,fr
2389
		C67_NOP(9);
2390
	    } else {
2391
		C67_MPYSP(r, fr);	// MPY  fr,r,fr
2392
		C67_NOP(3);
2393
	    }
2394
	    vtop--;
2395
	} else if (op == '/') {
2396
	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
2397
		// must call intrinsic DP floating point divide
2398
		vswap();
2399
		/* call generic idiv function */
2400
		vpush_global_sym(&func_old_type, TOK__divd);
2401
		vrott(3);
2402
		gfunc_call(2);
2403
		vpushi(0);
2404
		vtop->r = REG_FRET;
2405
		vtop->r2 = REG_LRET;
2406
 
2407
	    } else {
2408
		// must call intrinsic SP floating point divide
2409
		vswap();
2410
		/* call generic idiv function */
2411
		vpush_global_sym(&func_old_type, TOK__divf);
2412
		vrott(3);
2413
		gfunc_call(2);
2414
		vpushi(0);
2415
		vtop->r = REG_FRET;
2416
		vtop->r2 = VT_CONST;
2417
	    }
2418
	} else
2419
	    ALWAYS_ASSERT(FALSE);
2420
 
2421
 
2422
    }
2423
}
2424
 
2425
 
2426
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2427
   and 'long long' cases. */
2428
void gen_cvt_itof(int t)
2429
{
2430
    int r;
2431
 
2432
    gv(RC_INT);
2433
    r = vtop->r;
2434
 
2435
    if ((t & VT_BTYPE) == VT_DOUBLE) {
2436
	if (t & VT_UNSIGNED)
2437
	    C67_INTDPU(r, r);
2438
	else
2439
	    C67_INTDP(r, r);
2440
 
2441
	C67_NOP(4);
2442
	vtop->type.t = VT_DOUBLE;
2443
    } else {
2444
	if (t & VT_UNSIGNED)
2445
	    C67_INTSPU(r, r);
2446
	else
2447
	    C67_INTSP(r, r);
2448
	C67_NOP(3);
2449
	vtop->type.t = VT_FLOAT;
2450
    }
2451
 
2452
}
2453
 
2454
/* convert fp to int 't' type */
2455
/* XXX: handle long long case */
2456
void gen_cvt_ftoi(int t)
2457
{
2458
    int r;
2459
 
2460
    gv(RC_FLOAT);
2461
    r = vtop->r;
2462
 
2463
    if (t != VT_INT)
6429 siemargl 2464
	tcc_error("long long not supported");
145 halyavin 2465
    else {
2466
	if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2467
	    C67_DPTRUNC(r, r);
2468
	    C67_NOP(3);
2469
	} else {
2470
	    C67_SPTRUNC(r, r);
2471
	    C67_NOP(3);
2472
	}
2473
 
2474
	vtop->type.t = VT_INT;
2475
 
2476
    }
2477
}
2478
 
2479
/* convert from one floating point type to another */
2480
void gen_cvt_ftof(int t)
2481
{
2482
    int r, r2;
2483
 
2484
    if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2485
	(t & VT_BTYPE) == VT_FLOAT) {
2486
	// convert double to float
2487
 
2488
	gv(RC_FLOAT);		// get it in a register pair
2489
 
2490
	r = vtop->r;
2491
 
2492
	C67_DPSP(r, r);		// convert it to SP same register
2493
	C67_NOP(3);
2494
 
2495
	vtop->type.t = VT_FLOAT;
2496
	vtop->r2 = VT_CONST;	// set this as unused
2497
    } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
2498
	       (t & VT_BTYPE) == VT_DOUBLE) {
2499
	// convert float to double
2500
 
2501
	gv(RC_FLOAT);		// get it in a register
2502
 
2503
	r = vtop->r;
2504
 
2505
	if (r == TREG_EAX) {	// make sure the paired reg is avail
2506
	    r2 = get_reg(RC_ECX);
2507
	} else if (r == TREG_EDX) {
2508
	    r2 = get_reg(RC_ST0);
2509
	} else {
2510
	    ALWAYS_ASSERT(FALSE);
2511
            r2 = 0; /* avoid warning */
2512
        }
2513
 
2514
	C67_SPDP(r, r);		// convert it to DP same register
2515
	C67_NOP(1);
2516
 
2517
	vtop->type.t = VT_DOUBLE;
2518
	vtop->r2 = r2;		// set this as unused
2519
    } else {
2520
	ALWAYS_ASSERT(FALSE);
2521
    }
2522
}
2523
 
2524
/* computed goto support */
2525
void ggoto(void)
2526
{
2527
    gcall_or_jmp(1);
2528
    vtop--;
2529
}
2530
 
6429 siemargl 2531
/* Save the stack pointer onto the stack and return the location of its address */
2532
ST_FUNC void gen_vla_sp_save(int addr) {
2533
    tcc_error("variable length arrays unsupported for this target");
2534
}
2535
 
2536
/* Restore the SP from a location on the stack */
2537
ST_FUNC void gen_vla_sp_restore(int addr) {
2538
    tcc_error("variable length arrays unsupported for this target");
2539
}
2540
 
2541
/* Subtract from the stack pointer, and push the resulting value onto the stack */
2542
ST_FUNC void gen_vla_alloc(CType *type, int align) {
2543
    tcc_error("variable length arrays unsupported for this target");
2544
}
2545
 
2546
/* end of C67 code generator */
145 halyavin 2547
/*************************************************************/
6429 siemargl 2548
#endif
2549
/*************************************************************/