summaryrefslogtreecommitdiff
path: root/src/cmd/5l/softfloat.c
blob: de6481c7102d503f0141f25f99227c536e06749a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include	"l.h"
#include	"../ld/lib.h"

// Software floating point.

void
softfloat(void)
{
	Prog *p, *next, *psfloat;
	Sym *symsfloat;
	int wasfloat;

	if(!debug['F'])
		return;

	symsfloat = lookup("_sfloat", 0);
	psfloat = P;
	if(symsfloat->type == STEXT)
		psfloat = symsfloat->text;

	for(cursym = textp; cursym != nil; cursym = cursym->next) {
		wasfloat = 0;
		for(p = cursym->text; p != P; p = p->link)
			if(p->cond != P)
				p->cond->mark |= LABEL;
		for(p = cursym->text; p != P; p = p->link) {
			switch(p->as) {
			case AMOVW:
				if(p->to.type == D_FREG || p->from.type == D_FREG)
					goto soft;
				goto notsoft;

			case AMOVWD:
			case AMOVWF:
			case AMOVDW:
			case AMOVFW:
			case AMOVFD:
			case AMOVDF:
			case AMOVF:
			case AMOVD:

			case ACMPF:
			case ACMPD:
			case AADDF:
			case AADDD:
			case ASUBF:
			case ASUBD:
			case AMULF:
			case AMULD:
			case ADIVF:
			case ADIVD:
			case ASQRTF:
			case ASQRTD:
			case AABSF:
			case AABSD:
				goto soft;

			default:
				goto notsoft;

			soft:
				if (psfloat == P)
					diag("floats used with _sfloat not defined");
				if (!wasfloat || (p->mark&LABEL)) {
					next = prg();
					*next = *p;
	
					// BL _sfloat(SB)
					*p = zprg;
					p->link = next;
					p->as = ABL;
	 				p->to.type = D_BRANCH;
					p->to.sym = symsfloat;
					p->cond = psfloat;
					p->line = next->line;
	
					p = next;
					wasfloat = 1;
				}
				break;

			notsoft:
				wasfloat = 0;
			}
		}
	}
}