1/*	Id: local2.c,v 1.26 2011/06/23 13:41:25 ragge Exp 	*/
2/*	$NetBSD$	*/
3
4/*
5 * Copyright (c) 2008 David Crawshaw <david@zentus.com>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pass1.h"
21#include "pass2.h"
22
23
24char *
25rnames[] = {
26	/* "\%g0", always zero, removed due to 31-element class limit */
27	        "\%g1", "\%g2", "\%g3", "\%g4", "\%g5", "\%g6", "\%g7",
28	"\%o0", "\%o1", "\%o2", "\%o3", "\%o4", "\%o5", "\%o6", "\%o7",
29	"\%l0", "\%l1", "\%l2", "\%l3", "\%l4", "\%l5", "\%l6", "\%l7",
30	"\%i0", "\%i1", "\%i2", "\%i3", "\%i4", "\%i5", "\%i6", "\%i7",
31
32	"\%f0",  "\%f1",  "\%f2",  "\%f3",  "\%f4",  "\%f5",  "\%f6",  "\%f7",
33	"\%f8",  "\%f9",  "\%f10", "\%f11", "\%f12", "\%f13", "\%f14", "\%f15",
34	"\%f16", "\%f17", "\%f18", "\%f19", "\%f20", "\%f21", "\%f22", "\%f23",
35	"\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30",
36	/*, "\%f31" XXX removed due to 31-element class limit */
37
38	"\%f0",  "\%f2",  "\%f4",  "\%f6",  "\%f8",  "\%f10", "\%f12", "\%f14",
39	"\%f16", "\%f18", "\%f20", "\%f22", "\%f24", "\%f26", "\%f28", "\%f30",
40
41	"\%sp", "\%fp",
42};
43
44void
45deflab(int label)
46{
47	printf(LABFMT ":\n", label);
48}
49
50void
51prologue(struct interpass_prolog *ipp)
52{
53	int i, stack;
54
55	stack = V9RESERVE + V9STEP(p2maxautooff);
56
57	for (i = ipp->ipp_regs[0]; i; i >>= 1)
58		if (i & 1)
59			stack += 16;
60
61	/* TODO printf("\t.proc %d\n"); */
62	if (SIMM13(stack))
63		printf("\tsave %%sp,-%d,%%sp\n", stack);
64	else {
65		printf("\tsetx -%d,%%g4,%%g1\n", stack);
66		printf("\tsave %%sp,%%g1,%%sp\n");
67	}
68}
69
70void
71eoftn(struct interpass_prolog *ipp)
72{
73	printf("\tret\n");
74	printf("\trestore\n");
75	printf("\t.type %s,#function\n", ipp->ipp_name);
76	printf("\t.size %s,(.-%s)\n", ipp->ipp_name, ipp->ipp_name);
77}
78
79void
80hopcode(int f, int o)
81{
82	char *str;
83
84	switch (o) {
85		case EQ:        str = "brz"; break;
86		case NE:        str = "brnz"; break;
87		case ULE:
88		case LE:        str = "brlez"; break;
89		case ULT:
90		case LT:        str = "brlz";  break;
91		case UGE:
92		case GE:        str = "brgez"; break;
93		case UGT:
94		case GT:        str = "brgz";  break;
95		case PLUS:      str = "add"; break;
96		case MINUS:     str = "sub"; break;
97		case AND:       str = "and"; break;
98		case OR:        str = "or";  break;
99		case ER:        str = "xor"; break;
100		default:
101			comperr("unknown hopcode: %d (with %c)", o, f);
102			return;
103	}
104
105	printf("%s%c", str, f);
106}
107
108int
109tlen(NODE *p)
110{
111	switch (p->n_type) {
112		case CHAR:
113		case UCHAR:
114			return 1;
115		case SHORT:
116		case USHORT:
117			return (SZSHORT / SZCHAR);
118		case FLOAT:
119			return (SZFLOAT / SZCHAR);
120		case DOUBLE:
121			return (SZDOUBLE / SZCHAR);
122		case INT:
123		case UNSIGNED:
124			return (SZINT / SZCHAR);
125		case LONG:
126		case ULONG:
127		case LONGLONG:
128		case ULONGLONG:
129			return SZLONGLONG / SZCHAR;
130		default:
131			if (!ISPTR(p->n_type))
132				comperr("tlen type unknown: %d");
133			return SZPOINT(p->n_type) / SZCHAR;
134	}
135}
136
137void
138zzzcode(NODE * p, int c)
139{
140	char *str;
141	NODE *l, *r;
142	l = p->n_left;
143	r = p->n_right;
144
145	switch (c) {
146
147	case 'A':	/* Add const. */
148		if (ISPTR(l->n_type) && l->n_rval == FP)
149			r->n_lval += V9BIAS;
150
151		if (SIMM13(r->n_lval))
152			expand(p, 0, "\tadd AL,AR,A1\t\t! add const\n");
153		else
154			expand(p, 0, "\tsetx AR,A3,A2\t\t! add const\n"
155			             "\tadd AL,A2,A1\n");
156		break;
157	case 'B':	/* Subtract const. */
158		if (ISPTR(l->n_type) && l->n_rval == FP)
159			r->n_lval -= V9BIAS;
160
161		if (SIMM13(r->n_lval))
162			expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const\n");
163		else
164			expand(p, 0, "\tsetx AR,A3,A2\t\t! subtract const\n"
165			             "\tsub AL,A2,A1\n");
166		break;
167	case 'C':	/* Load constant to register. */
168		if (ISPTR(p->n_type))
169			expand(p, 0,
170				"\tsethi %h44(AL),A1\t\t! load label\n"
171				"\tor A1,%m44(AL),A1\n"
172				"\tsllx A1,12,A1\n"
173				"\tor A1,%l44(AL),A1\n");
174		else if (SIMM13(p->n_lval))
175			expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n");
176		else
177			expand(p, 0, "\tsetx AL,A2,A1\t\t! load const\n");
178		break;
179	case 'F':	/* Floating-point comparison, cf. hopcode(). */
180		switch (p->n_op) {
181			case EQ:        str = "fbe"; break;
182			case NE:        str = "fbne"; break;
183			case ULE:
184			case LE:        str = "fbule"; break;
185			case ULT:
186			case LT:        str = "fbul";  break;
187			case UGE:
188			case GE:        str = "fbuge"; break;
189			case UGT:
190			case GT:        str = "fbug";  break;
191			/* XXX
192			case PLUS:      str = "add"; break;
193			case MINUS:     str = "sub"; break;
194			case AND:       str = "and"; break;
195			case OR:        str = "or";  break;
196			case ER:        str = "xor"; break;*/
197			default:
198				comperr("unknown float code: %d", p->n_op);
199				return;
200		}
201		printf(str);
202		break;
203
204	case 'Q':	/* Structure assignment. */
205		/* TODO Check if p->n_stsize is small and use a few ldx's
206		        to move the struct instead of memcpy. The equiv.
207			could be done on all the architectures. */
208		if (l->n_rval != O0)
209			printf("\tmov %s,%s\n", rnames[l->n_rval], rnames[O0]);
210		if (SIMM13(p->n_stsize))
211			printf("\tor %%g0,%d,%%o2\n", p->n_stsize);
212		else
213			printf("\tsetx %d,%%g1,%%o2\n", p->n_stsize);
214		printf("\tcall memcpy\t\t\t! struct assign (dest, src, len)\n");
215		printf("\tnop\n");
216		break;
217	default:
218		cerror("unknown zzzcode call: %c", c);
219	}
220}
221
222int
223rewfld(NODE * p)
224{
225	return (1);
226}
227
228int
229fldexpand(NODE *p, int cookie, char **cp)
230{
231	printf("XXX fldexpand called\n"); /* XXX */
232	return 1;
233}
234
235int
236flshape(NODE * p)
237{
238	return SRREG;
239}
240
241int
242shtemp(NODE * p)
243{
244	return 0;
245}
246
247
248void
249adrcon(CONSZ val)
250{
251}
252
253void
254conput(FILE * fp, NODE * p)
255{
256	if (p->n_op != ICON) {
257		comperr("conput got bad op: %s", copst(p->n_op));
258		return;
259	}
260
261	if (p->n_name[0] != '\0') {
262		fprintf(fp, "%s", p->n_name);
263		if (p->n_lval > 0)
264			fprintf(fp, "+");
265		if (p->n_lval)
266			fprintf(fp, CONFMT, p->n_lval);
267	} else
268		fprintf(fp, CONFMT, p->n_lval);
269}
270
271void
272insput(NODE * p)
273{
274	comperr("insput");
275}
276
277void
278upput(NODE *p, int size)
279{
280	comperr("upput");
281}
282
283void
284adrput(FILE * io, NODE * p)
285{
286	int64_t off;
287
288	if (p->n_op == FLD) {
289		printf("adrput a FLD\n");
290		p = p->n_left;
291	}
292
293	if (p->n_op == UMUL && p->n_right == 0)
294		p = p->n_left;
295
296	off = p->n_lval;
297
298	switch (p->n_op) {
299	case NAME:
300		if (p->n_name[0] != '\0')
301			fputs(p->n_name, io);
302		if (off > 0)
303			fprintf(io, "+");
304		if (off != 0)
305			fprintf(io, CONFMT, (long long int)off);
306		return;
307	case OREG:
308		fprintf(io, "%s", rnames[p->n_rval]);
309		if (p->n_rval == FP)
310			off += V9BIAS;
311		if (p->n_rval == SP)
312			off += V9BIAS + V9RESERVE;
313		if (off > 0)
314			fprintf(io, "+");
315		if (off)
316			fprintf(io, CONFMT, (CONSZ)off);
317		return;
318	case ICON:
319		/* addressable value of the constant */
320		conput(io, p);
321		return;
322	case REG:
323		fputs(rnames[p->n_rval], io);
324		return;
325	case FUNARG:
326		/* We do something odd and store the stack offset in n_rval. */
327		fprintf(io, "%d", V9BIAS + V9RESERVE + p->n_rval);
328		return;
329	default:
330		comperr("bad address, %s, node %p", copst(p->n_op), p);
331		return;
332	}
333}
334
335void
336cbgen(int o, int lab)
337{
338}
339
340void
341myreader(struct interpass * ipole)
342{
343}
344
345void
346mycanon(NODE * p)
347{
348}
349
350void
351myoptim(struct interpass * ipole)
352{
353}
354
355void
356rmove(int s, int d, TWORD t)
357{
358	printf("\t");
359
360	if (t == FLOAT)	      printf("fmovs");
361	else if (t == DOUBLE) printf("fmovd");
362	else                  printf("mov");
363
364	printf(" %s,%s\t\t\t! rmove()\n", rnames[s], rnames[d]);
365}
366
367int
368gclass(TWORD t)
369{
370	if (t == FLOAT)
371		return CLASSB;
372	if (t == DOUBLE)
373		return CLASSC;
374	return CLASSA;
375}
376
377void
378lastcall(NODE *p)
379{
380}
381
382int
383special(NODE *p, int shape)
384{
385	return SRNOPE;
386}
387
388void mflags(char *str)
389{
390}
391
392int
393COLORMAP(int c, int *r)
394{
395	int num=0;
396
397	switch (c) {
398		case CLASSA:
399			num += r[CLASSA];
400			return num < 32;
401		case CLASSB:
402			num += r[CLASSB];
403			num += 2*r[CLASSC];
404			return num < 32;;
405		case CLASSC:
406			num += r[CLASSC];
407			num += 2*r[CLASSB];
408			return num < 17;
409		case CLASSD:
410			return 0;
411		default:
412			comperr("COLORMAP: unknown class: %d", c);
413			return 0;
414	}
415}
416/*
417 * Do something target-dependent for xasm arguments.
418 * Supposed to find target-specific constraints and rewrite them.
419 */
420int
421myxasm(struct interpass *ip, NODE *p)
422{
423	return 0;
424}
425