summaryrefslogtreecommitdiff
path: root/bcc/floatop.c
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-03-24 17:45:55 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:29:43 +0200
commitfe22c37817ce338fbbc90b239320248c270957fa (patch)
treed9550410c4a20bdd382fcc58d2d3d7c5e04e5245 /bcc/floatop.c
parenta7aba15e8efffb1c5d3097656f1a93955a64f01f (diff)
parent42192453ea219b80d0bf9f41e51e36d3d4d0740b (diff)
downloaddev86-fe22c37817ce338fbbc90b239320248c270957fa.tar.gz
Import Dev86-0.0.4.tar.gzv0.0.4
Diffstat (limited to 'bcc/floatop.c')
-rw-r--r--bcc/floatop.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/bcc/floatop.c b/bcc/floatop.c
new file mode 100644
index 0000000..fb9c54d
--- /dev/null
+++ b/bcc/floatop.c
@@ -0,0 +1,173 @@
+/* floatop.c - software operations on floats and doubles for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ f_indirect(target leaf)
+ make the float or double target indirect if it is not already
+ return nonzero iff the result is a temp double on the base of the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC bool_pt f_indirect(target)
+struct symstruct *target;
+{
+ if (target->indcount == 0)
+ {
+ if (target->storage == CONSTANT)
+ {
+ /* XXX - more for non-386 */
+ if (target->type->scalar & FLOAT)
+ {
+ float val;
+
+ val = *target->offset.offd;
+ push(constsym(((value_t *) &val)[0]));
+ }
+ else
+ {
+ push(constsym(((value_t *) target->offset.offd)[1]));
+ push(constsym(((value_t *) target->offset.offd)[0]));
+ }
+ }
+ else if (target->type->scalar & FLOAT)
+ pushlist(target->storage); /* XXX - floatregs */
+ else
+ pushlist(doubleregs);
+ onstack(target);
+ }
+ return target->flags == TEMP && target->type->scalar & DOUBLE
+ && target->offset.offi == sp;
+}
+
+/*-----------------------------------------------------------------------------
+ float1op(operation code, source leaf)
+ handles all flop unary operations except inc/dec
+ result is double on stack (or in condition codes for EQOP)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void float1op(op, source)
+op_pt op;
+struct symstruct *source;
+{
+ saveopreg();
+ pointat(source);
+ if ((op_t) op == NEGOP)
+ call("Fneg");
+ else /* op == EQOP */
+ call("Ftst");
+ outntypechar(source->type);
+ if ((op_t) op != EQOP)
+ justpushed(source);
+ restoreopreg();
+}
+
+/*-----------------------------------------------------------------------------
+ floatop(operation code, source leaf, target leaf)
+ handles all flop binary operations
+ result is double on stack (or in condition codes for EQOP)
+----------------------------------------------------------------------------*/
+
+PUBLIC void floatop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regmark;
+ bool_t sflag;
+
+ regmark = reguse;
+ saveopreg();
+ (void) f_indirect(source);
+ if (!(reguse & OPREG) && (source->storage == OPREG))
+ {
+ reguse |= source->storage;
+ saveopreg();
+ }
+ fpush(target);
+ sflag = TRUE;
+ if (source->flags != TEMP || source->offset.offi != sp + dtypesize)
+ {
+ sflag = FALSE;
+ if (source->storage == OPREG)
+ restoreopreg();
+ pointat(source);
+ }
+ switch ((op_t) op)
+ {
+ case ADDOP:
+ call("Fadd");
+ break;
+ case DIVOP:
+ call("Fdiv");
+ break;
+ case EQOP:
+ call("Fcomp");
+ sp += dtypesize; /* target is popped */
+ break; /* target symbol now invalid but is not used */
+ case MULOP:
+ call("Fmul");
+ break;
+ case SUBOP:
+ call("Fsub");
+ break;
+ }
+ if (sflag)
+ {
+ outnl();
+ sp += dtypesize; /* source is popped */
+ }
+ else
+ outntypechar(source->type);
+ onstack(target);
+ reguse = regmark; /* early so opreg is not reloaded if source */
+ restoreopreg();
+}
+
+/*-----------------------------------------------------------------------------
+ fpush(source leaf of scalar type)
+ converts source to double and pushes it to stack
+ OPREG must be free
+-----------------------------------------------------------------------------*/
+
+PUBLIC void fpush(source)
+struct symstruct *source;
+{
+ scalar_t scalar;
+
+ if ((scalar = source->type->scalar) & RSCALAR)
+ {
+ if (f_indirect(source))
+ return;
+ pointat(source);
+ }
+ else if (scalar & DLONG)
+ load(source, OPREG);
+ else
+ load(source, DREG);
+ call("Fpush");
+ if (scalar & UNSIGNED)
+ outbyte('u');
+ outntypechar(source->type);
+ justpushed(source);
+}
+
+/*-----------------------------------------------------------------------------
+ justpushed(target leaf)
+ records that target has just been pushed to a double on the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC void justpushed(target)
+struct symstruct *target;
+{
+ sp -= dtypesize;
+ onstack(target);
+ target->type = dtype;
+}