diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-10-04 20:06:30 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-10-04 20:06:30 +0200 |
commit | 107ca1b42d099d74cd033be7f363b92d4ff29e3c (patch) | |
tree | 6ed5b6fcf039c98c0644ff6b820d6148c4414728 /sys/src/cmd/cc | |
parent | bfd0cb0db474a2ace38443537aff86382ec10baf (diff) |
cc: handle 64 bit mixedmode asop and type vlong <-> float/double type conversions
Diffstat (limited to 'sys/src/cmd/cc')
-rw-r--r-- | sys/src/cmd/cc/com64.c | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/sys/src/cmd/cc/com64.c b/sys/src/cmd/cc/com64.c index f44a44ffe..8847010b2 100644 --- a/sys/src/cmd/cc/com64.c +++ b/sys/src/cmd/cc/com64.c @@ -49,6 +49,8 @@ Node* noduc2v; Node* nodv2f; Node* nodv2d; +Node* noduv2f; +Node* noduv2d; Node* nodv2ui; Node* nodv2si; Node* nodv2ul; @@ -63,6 +65,11 @@ Node* nodppv; Node* nodvmm; Node* nodmmv; +Node* nodaddd; +Node* nodsubd; +Node* nodmuld; +Node* noddivd; + Node* nodvasop; char etconv[NTYPE]; /* for _vasop */ @@ -146,6 +153,8 @@ com64init(void) nodv2f = fvn("_v2f", TFLOAT); nodv2d = fvn("_v2d", TDOUBLE); + noduv2f = fvn("_uv2f", TFLOAT); + noduv2d = fvn("_uv2d", TDOUBLE); nodv2sl = fvn("_v2sl", TLONG); nodv2ul = fvn("_v2ul", TULONG); nodv2si = fvn("_v2si", TINT); @@ -160,6 +169,11 @@ com64init(void) nodvmm = fvn("_vmm", TVLONG); nodmmv = fvn("_mmv", TVLONG); + nodaddd = fvn("_vasaddd", TVLONG); + nodsubd = fvn("_vassubd", TVLONG); + nodmuld = fvn("_vasmuld", TVLONG); + noddivd = fvn("_vasdivd", TVLONG); + nodvasop = fvn("_vasop", TVLONG); for(p = initetconv; p->code >= 0; p++) @@ -416,38 +430,22 @@ com64(Node *n) } } - if(typefd[n->type->etype] && l && l->op == OFUNC) { - switch(n->op) { - case OASADD: - case OASSUB: - case OASMUL: - case OASLMUL: - case OASDIV: - case OASLDIV: - case OASMOD: - case OASLMOD: - case OASASHL: - case OASASHR: - case OASLSHR: - case OASAND: - case OASOR: - case OASXOR: - if(l->right && typev[l->right->etype]) { - diag(n, "sorry float <asop> vlong not implemented\n"); - } - } - } - if(n->op == OCAST) { if(l->type && typev[l->type->etype]) { if(machcap(n)) return 1; switch(n->type->etype) { case TDOUBLE: - a = nodv2d; + if(l->type->etype == TUVLONG) + a = noduv2d; + else + a = nodv2d; goto setfnx; case TFLOAT: - a = nodv2f; + if(l->type->etype == TUVLONG) + a = noduv2f; + else + a = nodv2f; goto setfnx; case TLONG: a = nodv2sl; @@ -524,9 +522,43 @@ setbool: return 1; setasop: - if(l->op == OFUNC) { + while(l->op == OFUNC) l = l->right; - goto setasop; + + if(mixedasop(n->left->type, n->right->type)) { + if(n->right->type->etype != TDOUBLE) { + r = new(OCAST, r, 0); + r->type = types[TDOUBLE]; + } + + if(l->type->etype == TUVLONG) + a = noduv2d; + else + a = nodv2d; + + t = new(OADDR, a, 0); + t->type = typ(TIND, a->type); + r = new(OLIST, t, r); + + t = new(OADDR, l, 0); + t->type = typ(TIND, l->type); + t->complex = l->complex; + r = new(OLIST, t, r); + + switch(n->op){ + default: diag(n, "mixed vlong/double %O not implemented", n->op); + case OASADD: a = nodaddd; break; + case OASSUB: a = nodsubd; break; + case OASMUL: a = nodmuld; break; + case OASDIV: a = noddivd; break; + } + + n->left = a; + n->right = r; + n->complex = FNX; + n->op = OFUNC; + + return 1; } t = new(OCONST, 0, 0); |