1 /* genloads.c - generate loads of registers and memory for bcc */
3 /* Copyright (C) 1992 Bruce Evans */
15 FORWARD
void badaddress
P((void));
16 FORWARD
void blockpush
P((struct symstruct
*source
));
17 FORWARD
void loadadr
P((struct symstruct
*source
, store_pt targreg
));
18 FORWARD
void loadlongindirect
P((struct symstruct
*source
, store_pt targreg
));
19 FORWARD
void outnamoffset
P((struct symstruct
*adr
));
20 FORWARD
void outnnadr
P((struct symstruct
*adr
));
21 FORWARD fastin_pt pushpull
P((store_pt reglist
, bool_pt pushflag
));
23 PUBLIC
void addoffset(source
)
24 struct symstruct
*source
;
27 if (source
->level
== OFFKLUDGELEVEL
)
30 outregname(source
->storage
);
35 if (source
->storage
& (AXREG
| ALREG
))
37 if (source
->level
== OFFKLUDGELEVEL
)
38 source
->level
= EXPRLEVEL
;
39 source
->offset
.offi
= 0;
43 if (source
->offset
.offi
!= 0)
45 addconst(source
->offset
.offi
, source
->storage
);
46 source
->offset
.offi
= 0;
50 PUBLIC
void address(source
)
51 struct symstruct
*source
;
53 if (source
->indcount
== 0)
54 bugerror("taking address of non-lvalue");
57 if (source
->type
->constructor
& (ARRAY
| FUNCTION
))
58 bugerror("botched indirect array or function");
59 else if (--source
->indcount
== 0 && source
->storage
== GLOBAL
&&
60 !(source
->flags
& LABELLED
) && *source
->name
.namep
== 0)
61 source
->storage
= CONSTANT
;
62 source
->type
= pointype(source
->type
);
66 PRIVATE
void badaddress()
68 bugerror("bad address");
71 PRIVATE
void blockpush(source
)
72 struct symstruct
*source
;
74 struct symstruct
*length
;
78 typesize
= source
->type
->typesize
;
79 length
= constsym((value_t
) typesize
);
80 length
->type
= uitype
;
82 modstk(spmark
= sp
- (offset_T
) typesize
);
84 regtransfer(STACKREG
, DREG
);
86 #ifdef MC6809 /* XXX ? */
87 regtransfer(LOCAL
, DREG
);
89 #include "need STACKREG and stackregstr"
101 PUBLIC
void exchange(source
, target
)
102 struct symstruct
*source
;
103 struct symstruct
*target
;
107 regexchange(source
->storage
, target
->storage
);
108 tempreg
= target
->storage
;
109 target
->storage
= source
->storage
;
110 source
->storage
= tempreg
;
113 /*-----------------------------------------------------------------------------
115 returns the "best" available index register
116 -----------------------------------------------------------------------------*/
118 PUBLIC store_pt
getindexreg()
120 if (!(reguse
& INDREG0
))
122 if (!(reguse
& INDREG1
))
124 if (!(reguse
& INDREG2
))
130 if (!(reguse
& DATREG1
))
132 if (!(reguse
& DATREG2
))
137 bugerror("out of index regs");
141 /*-----------------------------------------------------------------------------
142 indexadr(index leaf, pointer leaf)
143 is used by the index and add and subtract (pointer) routines
144 it handles expressions like
147 the target becomes register direct with offset
148 (except for index = 0, when nothing is changed)
149 constant indexes are optimised by leaving them as offsets
150 register direct pointers are optimised by leaving the offset alone
151 (except for PC register direct, since there is no LEAX D,PC)
152 -----------------------------------------------------------------------------*/
154 PUBLIC
void indexadr(source
, target
)
155 struct symstruct
*source
;
156 struct symstruct
*target
;
163 struct typestruct
*targtype
;
166 if (!(target
->type
->constructor
& (ARRAY
| POINTER
)))
168 bugerror("cannot index");
171 size
= target
->type
->nexttype
->typesize
;
172 if (source
->storage
== CONSTANT
)
174 if (source
->offset
.offv
!= 0)
176 if (target
->indcount
!= 0)
178 target
->offset
.offi
+= source
->offset
.offv
* size
;
182 if (target
->storage
& ALLDATREGS
)
184 if ((store_t
) (sourcereg
= target
->storage
) & ~reguse
& allindregs
)
187 targreg
= getindexreg();
189 if ((store_t
) sourcereg
== GLOBAL
&& target
->indcount
== 0 &&
190 !(source
->type
->scalar
& CHAR
) && source
->storage
!= DREG
)
191 load(source
, targreg
);
197 softop(MULOP
, constsym((value_t
) size
), source
);
201 /*-----------------------------------------------------------------------------
202 do some calculations in advance to decide if index can be done with ABX
203 -----------------------------------------------------------------------------*/
205 if ((store_t
) targreg
== XREG
&& source
->type
->scalar
& CHAR
&&
211 softop(MULOP
, constsym((value_t
) size
), source
);
216 /*-----------------------------------------------------------------------------
217 deal with constant target - constant becomes offset, result in DREG
218 -----------------------------------------------------------------------------*/
220 if (target
->storage
== CONSTANT
)
222 target
->storage
= DREG
;
226 /*-----------------------------------------------------------------------------
227 load target if it is indirect or GLOBAL or canABX so D or B can be added
228 otherwise, it is register direct (maybe S register, maybe with offset)
229 and the offset can be left after adding DREG
230 -----------------------------------------------------------------------------*/
233 if (target
->indcount
!= 0)
235 targtype
= target
->type
;
236 target
->type
= itype
;
238 target
->type
= targtype
;
241 if ((store_t
) sourcereg
== GLOBAL
)
243 target
->storage
= source
->storage
;
244 target
->level
= OFFKLUDGELEVEL
;
249 if (canABX
|| (store_t
) sourcereg
== GLOBAL
)
251 load(target
, targreg
);
254 else if (target
->indcount
!= 0)
256 targtype
= target
->type
;
257 target
->type
= itype
;
259 target
->type
= targtype
;
269 if ((store_t
) targreg
!= (store_t
) sourcereg
)
270 regtransfer(sourcereg
, targreg
);
280 outncregname(sourcereg
);
283 if ((store_t
) sourcereg
== LOCAL
)
285 target
->offset
.offi
-= framep
;
287 target
->offset
.offi
-= sp
;
289 target
->storage
= targreg
;
292 PUBLIC
void indirec(source
)
293 struct symstruct
*source
;
295 if (!(source
->type
->constructor
& (ARRAY
| POINTER
)))
296 bugerror("illegal indirection");
297 else if (source
->indcount
== (indn_t
) - 1)
298 limiterror("too many indirections (256)");
301 if (source
->storage
& ALLDATREGS
)
302 transfer(source
, getindexreg());
303 if (!((source
->type
= source
->type
->nexttype
)->constructor
&
306 if (source
->storage
== CONSTANT
)
307 source
->storage
= GLOBAL
;
311 /*-----------------------------------------------------------------------------
312 load(source leaf, target register)
313 loads the specified register without changing any others (except CC)
314 if the type is long or float, DREG is paired with the target register
315 the result has no offset
316 -----------------------------------------------------------------------------*/
318 PUBLIC
void load(source
, targreg
)
319 struct symstruct
*source
;
322 if (source
->type
->scalar
& DLONG
)
324 if (source
->storage
== CONSTANT
)
325 loadreg(source
, targreg
);
326 else if (source
->indcount
== 0)
328 #if DYNAMIC_LONG_ORDER
329 if (!long_big_endian
)
331 #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
333 if ((store_t
) targreg
== DREG
)
334 source
->storage
= DREG
;
337 if (source
->storage
!= (store_t
) targreg
)
338 transfer(source
, targreg
);
339 if (source
->offset
.offi
!= 0)
340 bugerror("loading direct long with offset not implemented");
343 loadlongindirect(source
, targreg
);
345 else if (source
->type
->scalar
& DOUBLE
)
347 if (source
->storage
== targreg
&& source
->indcount
== 0)
349 if (source
->storage
== CONSTANT
)
354 loadconst(((offset_T
*) source
->offset
.offd
)[0], DREG
);
355 loadconst(((offset_T
*) source
->offset
.offd
)[1], targreg
&~DREG
);
357 else /* XXX - more for non-386 */
361 loadconst(((unsigned short *) source
->offset
.offd
)[0], DREG
);
362 regs
= (targreg
&~DREG
);
367 ((unsigned short *) source
->offset
.offd
)[off
++],
375 poplist(targreg
| DREG
); /* actually it's the full reg list */
377 source
->storage
= targreg
; /* XXX - multi for non-386 */
378 source
->indcount
= 0;
380 if (source
->level
== OFFKLUDGELEVEL
)
381 source
->level
= EXPRLEVEL
;
382 source
->offset
.offi
= 0;
384 else if (source
->type
->scalar
& FLOAT
&& source
->storage
== CONSTANT
)
388 val
= *source
->offset
.offd
;
391 loadconst(((offset_T
*) &val
)[0], targreg
); /* XXX 386 */
395 loadconst(((unsigned short *) &val
)[0], DREG
);
396 loadconst(((unsigned short *) &val
)[1], targreg
&~DREG
);
400 else if (!i386_32
&& source
->type
->scalar
& FLOAT
)
402 else if (source
->type
->scalar
& FLOAT
)
405 /* Treat a float just like a long ... */
406 if (source
->indcount
== 0)
408 if (source
->storage
!= (store_t
) targreg
)
409 transfer(source
, targreg
);
410 if (source
->offset
.offi
!= 0)
411 bugerror("loading direct float with offset not implemented");
414 loadlongindirect(source
, targreg
);
416 else if (source
->indcount
== 0 && source
->storage
!= CONSTANT
)
417 loadadr(source
, targreg
);
418 else if (source
->type
->scalar
||
419 source
->type
->constructor
& (ARRAY
| POINTER
))
420 loadreg(source
, targreg
);
422 bugerror("attempting to load non-scalar non-pointer");
425 PRIVATE
void loadadr(source
, targreg
)
426 struct symstruct
*source
;
429 if ((store_t
) targreg
& ALLDATREGS
)
431 if (source
->storage
== GLOBAL
)
437 loadreg(source
, INDREG0
);
438 transfer(source
, DREG
);
443 loadreg(source
, targreg
);
445 if (source
->storage
== LOCAL
)
447 source
->offset
.offi
-= framep
;
449 source
->offset
.offi
-= sp
;
451 if (source
->type
->scalar
& CHAR
)
454 if (source
->storage
== DREG
)
457 if (source
->storage
!= (store_t
) targreg
)
458 transfer(source
, targreg
);
461 else if (source
->storage
& ALLDATREGS
)
464 transfer(source
, targreg
);
466 else if (source
->storage
!= (store_t
) targreg
||
467 source
->offset
.offi
!= 0 || source
->level
== OFFKLUDGELEVEL
)
468 loadreg(source
, targreg
);
471 PUBLIC
void loadany(source
)
472 struct symstruct
*source
;
474 if (source
->indcount
!= 0 || source
->offset
.offi
!= 0 || /* kludge u cmp */
475 source
->level
== OFFKLUDGELEVEL
|| !(source
->storage
& allregs
))
477 if (source
->type
->scalar
& RSCALAR
)
478 load(source
, doubleregs
& ~DREG
);
479 else if ((source
->storage
== CONSTANT
&&
480 !(source
->type
->scalar
& DLONG
))
481 || source
->type
->scalar
& CHAR
)
483 else if (source
->storage
& ~reguse
& allregs
)
484 load(source
, source
->storage
);
485 else if (((reguse
& allindregs
) == allindregs
||
486 ((!(source
->type
->constructor
& (ARRAY
| POINTER
)) &&
487 source
->indcount
!= 0) &&
488 !(source
->type
->scalar
& DLONG
))))
491 load(source
, getindexreg());
495 PRIVATE
void loadlongindirect(source
, targreg
)
496 struct symstruct
*source
;
502 struct typestruct
*type
;
504 if (source
->level
== OFFKLUDGELEVEL
)
505 addoffset(source
); /* else kludge is lost and offsets big */
506 flags
= source
->flags
;
507 offset
= source
->offset
.offi
;
508 reg
= source
->storage
;
510 source
->type
= itype
;
511 loadreg(source
, DREG
);
512 source
->flags
= flags
;
513 source
->storage
= reg
;
514 source
->indcount
= 1;
515 source
->offset
.offi
= offset
+ accregsize
;
516 loadreg(source
, targreg
);
520 PUBLIC
void loadreg(source
, targreg
)
521 struct symstruct
*source
;
527 if (source
->storage
== CONSTANT
)
529 if (source
->type
->scalar
& CHAR
&& (store_t
) targreg
& ALLDATREGS
)
531 longlow
= (offset_T
) source
->offset
.offv
;
532 if (source
->type
->scalar
& DLONG
)
534 longlow
&= (offset_T
) intmaskto
;
535 longhigh
= (offset_T
) (source
->offset
.offv
>> INT16BITSTO
)
536 & (offset_T
) intmaskto
;
537 if ((store_t
) targreg
!= LONGREG2
) /* loading the whole long */
539 #if DYNAMIC_LONG_ORDER
542 #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
543 loadconst(longhigh
, DREG
);
545 #if DYNAMIC_LONG_ORDER
548 #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
550 loadconst(longlow
, DREG
);
556 loadconst(longlow
, targreg
);
557 source
->storage
= targreg
;
558 source
->offset
.offi
= 0;
563 if (source
->indcount
== 0 && source
->storage
!= GLOBAL
&&
564 (source
->offset
.offi
!= 0 || source
->level
== OFFKLUDGELEVEL
))
566 if ((store_t
) targreg
== source
->storage
)
571 source
->indcount
= 1; /* fake for outadr() to produce "()" */
577 /* Added acess to CPU registers. Just declare _AX etc. as
578 * extern int, and you can use them to get/set
579 * the register values. (vak) */
580 if (source
->storage
== GLOBAL
&& !(source
->flags
& LABELLED
) &&
581 *source
->name
.namep
!= 0 &&
582 strncmp(source
->name
.namep
, "__", 2) == 0)
584 if (strcmp (source
->name
.namep
, "__AX") == 0)
586 /* Load AX register - do nothing. */
588 if (targreg
!= AXREG
)
589 bugerror("specified access of register clone variable not implemented");
590 source
->storage
= AXREG
; /* in register for further use */
592 if (source
->level
== OFFKLUDGELEVEL
)
593 source
->level
= EXPRLEVEL
;
594 source
->offset
.offi
= 0; /* indcount was adjusted by outadr */
597 if (strcmp (source
->name
.namep
, "__BX") == 0) { outstr ("mov\tax,bx\n"); goto done
; }
598 if (strcmp (source
->name
.namep
, "__CX") == 0) { outstr ("mov\tax,cx\n"); goto done
; }
599 if (strcmp (source
->name
.namep
, "__DX") == 0) { outstr ("mov\tax,dx\n"); goto done
; }
600 if (strcmp (source
->name
.namep
, "__SP") == 0) { outstr ("mov\tax,sp\n"); goto done
; }
601 if (strcmp (source
->name
.namep
, "__BP") == 0) { outstr ("mov\tax,bp\n"); goto done
; }
602 if (strcmp (source
->name
.namep
, "__SI") == 0) { outstr ("mov\tax,si\n"); goto done
; }
603 if (strcmp (source
->name
.namep
, "__DI") == 0) { outstr ("mov\tax,di\n"); goto done
; }
604 if (strcmp (source
->name
.namep
, "__CS") == 0) { outstr ("mov\tax,cs\n"); goto done
; }
605 if (strcmp (source
->name
.namep
, "__DS") == 0) { outstr ("mov\tax,ds\n"); goto done
; }
606 if (strcmp (source
->name
.namep
, "__ES") == 0) { outstr ("mov\tax,es\n"); goto done
; }
607 if (strcmp (source
->name
.namep
, "__SS") == 0) { outstr ("mov\tax,ss\n"); goto done
; }
608 if (strcmp (source
->name
.namep
, "__FLAGS") == 0) { outstr ("pushf\npop\tax\n"); goto done
; }
612 if (source
->storage
== GLOBAL
&& source
->indcount
!= 0 &&
613 (store_t
) targreg
& (AXREG
| ALREG
))
618 if (source
->indcount
== 0 &&
619 (source
->storage
!= GLOBAL
|| posindependent
))
624 if ((store_t
) targreg
== YREG
)
628 movereg(source
, targreg
);
632 PUBLIC
void makelessindirect(source
)
633 struct symstruct
*source
;
637 if (!((store_t
) (lreg
= source
->storage
) & ~reguse
& allindregs
))
638 lreg
= getindexreg();
639 while (source
->indcount
> MAXINDIRECT
)
640 loadreg(source
, lreg
);
642 if (source
->indcount
== MAXINDIRECT
&&
643 (source
->type
->typesize
> maxregsize
||
644 source
->type
->constructor
& FUNCTION
))
646 source
->indcount
= 1;
647 loadreg(source
, lreg
);
648 source
->indcount
= 1;
653 PUBLIC
void movereg(source
, targreg
)
654 struct symstruct
*source
;
657 if ((store_t
) targreg
& ALLDATREGS
&& source
->type
->scalar
& CHAR
)
660 if (source
->type
->scalar
& CHAR
&&
661 targreg
!= BREG
&& targreg
!= DATREG1B
) {
662 bugerror("moving char sym into int register");
666 if (i386_32
&& source
->type
->scalar
& SHORT
&&
667 source
->indcount
<= 1)
669 outshortregname(targreg
);
675 if (source
->storage
== CONSTANT
)
676 adjlc((offset_T
) source
->offset
.offv
, targreg
);
681 source
->storage
= targreg
; /* in register for further use */
683 if (source
->level
== OFFKLUDGELEVEL
)
684 source
->level
= EXPRLEVEL
;
685 source
->offset
.offi
= 0; /* indcount was adjusted by outadr */
688 PUBLIC
void onstack(target
)
689 register struct symstruct
*target
;
691 target
->storage
= LOCAL
;
692 target
->flags
= TEMP
;
693 if (target
->level
== OFFKLUDGELEVEL
)
694 target
->level
= EXPRLEVEL
;
695 target
->indcount
= 1;
696 target
->offset
.offi
= sp
;
699 PUBLIC
void outadr(adr
)
700 struct symstruct
*adr
;
706 PUBLIC
void outcregname(reg
)
713 PRIVATE
void outnamoffset(adr
)
714 struct symstruct
*adr
;
716 if (adr
->flags
& LABELLED
)
717 outlabel(adr
->name
.label
);
719 outccname(adr
->name
.namep
);
720 if (adr
->offset
.offi
!= 0)
722 if (adr
->offset
.offi
> 0)
724 outshex(adr
->offset
.offi
);
733 /* print comma, then register name, then newline */
735 PUBLIC
void outncregname(reg
)
742 PRIVATE
void outnnadr(adr
)
743 struct symstruct
*adr
;
749 if (adr
->indcount
>= MAXINDIRECT
)
754 if (adr
->indcount
>= MAXINDIRECT
&& (adr
->indcount
& 1) == 0)
756 indflag
= TRUE
; /* indirection means double indirect */
760 switch (adr
->storage
)
763 outimmadr((offset_T
) adr
->offset
.offv
);
767 if (indflag
|| adr
->offset
.offi
!= 0 || adr
->level
== OFFKLUDGELEVEL
)
777 if (indflag
&& !i386_32
)
790 if (adr
->level
== OFFKLUDGELEVEL
)
799 else if (adr
->offset
.offi
!= 0)
801 outoffset(adr
->offset
.offi
);
805 outregname(adr
->storage
);
812 if (indflag
&& adr
->offset
.offi
!= 0 && is5bitoffset(adr
->offset
.offi
))
814 outcregname(adr
->storage
);
821 bugerror("no frame pointer");
824 if (adr
->offset
.offi
== framep
)
829 if (switchnow
!= NULL
&& adr
->flags
== TEMP
)
830 outswoffset(off
= adr
->offset
.offi
);
832 outoffset(off
= adr
->offset
.offi
- framep
);
834 if (optimise
&& !callersaves
&& off
< 0)
844 else if (adr
->offset
.offi
!= framep
)
851 if (adr
->offset
.offi
!= sp
)
852 outoffset(adr
->offset
.offi
- sp
);
855 else if (adr
->offset
.offi
!= sp
)
858 # endif /* FRAMEPOINTER */
865 if (adr
->flags
== TEMP
&& adr
->offset
.offi
== sp
&&
871 if (adr
->type
->typesize
!= 1)
878 outoffset(adr
->offset
.offi
- sp
);
879 if (indflag
&& adr
->offset
.offi
!= sp
&&
880 is5bitoffset(adr
->offset
.offi
- sp
))
905 if (adr
->indcount
== 0)
915 else if (adr
->flags
& DIRECTPAGE
)
924 if (adr
->flags
& LABELLED
)
925 outlabel(adr
->name
.label
);
926 else if (*adr
->name
.namep
== 0) /* constant address */
928 outhex((uoffset_T
) adr
->offset
.offi
);
932 outccname(adr
->name
.namep
);
933 if (adr
->offset
.offi
!= 0)
935 if (adr
->offset
.offi
> 0)
937 outshex(adr
->offset
.offi
);
965 adr
->indcount
-= MAXINDIRECT
;
967 else if (adr
->indcount
!= 0)
972 /* print register name, then newline */
974 PUBLIC
void outnregname(reg
)
981 /* print register name */
983 PUBLIC
void outregname(reg
)
986 switch ((store_t
) reg
)
1012 outstr(localregstr
);
1017 outstr(stackregstr
);
1053 #if defined(I8088) && defined(I80386)
1054 /* print register name for short type */
1056 PUBLIC
void outshortregname(reg
)
1059 switch ((store_t
) reg
)
1062 outstr(accumstr
+ 1);
1065 outstr(ireg0str
+ 1);
1068 outstr(ireg1str
+ 1);
1071 outstr(ireg2str
+ 1);
1074 outstr(dreg1str
+ 1);
1077 outstr(dreg2str
+ 1);
1087 /*-----------------------------------------------------------------------------
1088 pointat(target leaf)
1089 point OPREG at target
1090 target must be singly indirect or float or double
1091 -----------------------------------------------------------------------------*/
1093 PUBLIC
void pointat(target
)
1094 struct symstruct
*target
;
1096 if (target
->type
->scalar
& RSCALAR
)
1097 (void) f_indirect(target
);
1099 load(target
, OPREG
);
1100 target
->type
= target
->type
->nexttype
;
1103 PUBLIC
void poplist(reglist
)
1107 sp
+= pushpull(reglist
, FALSE
);
1110 PUBLIC
void push(source
)
1111 struct symstruct
*source
;
1119 if (source
->type
->constructor
& STRUCTU
)
1121 if (source
->flags
!= TEMP
) /* TEMP must be from last function */
1124 else if ((sscalar
= source
->type
->scalar
) & RSCALAR
)
1126 if (!f_indirect(source
))
1134 else if ((source
->indcount
== 1 &&
1135 (sscalar
& (SHORT
| INT
| LONG
| FLOAT
) ||
1136 source
->type
->constructor
& POINTER
))
1138 || (source
->storage
== CONSTANT
&& i386_32
)
1142 size
= source
->type
->typesize
;
1145 if (sscalar
& DLONG
)
1147 source
->offset
.offi
+= itypesize
;
1152 source
->indcount
= 1;
1153 source
->offset
.offi
-= itypesize
;
1161 if (source
->storage
== CONSTANT
)
1164 adjlc((offset_T
) source
->offset
.offv
, INDREG0
);
1181 reg
= source
->storage
;
1183 if (sscalar
& DLONG
)
1184 pushlist(DREG
| source
->storage
);
1185 else if (sscalar
& CHAR
)
1188 pushreg(source
->storage
);
1189 if (source
->flags
!= REGVAR
)
1190 reguse
&= ~(reg
| source
->storage
);
1195 PUBLIC
void pushlist(reglist
)
1198 if ((store_t
) reglist
)
1199 sp
-= pushpull(reglist
, TRUE
);
1202 PRIVATE fastin_pt
pushpull(reglist
, pushflag
)
1206 store_pt lastregbit
;
1207 void (*ppfunc
) P((void));
1211 int separator
; /* promoted char for output */
1214 fastin_t bytespushed
;
1217 if ((bool_t
) pushflag
)
1225 regptr
= regpushlist
;
1232 regptr
= regpulllist
;
1234 lastregbit
= 1 << 10;
1236 lastregbit
= 1 << 7;
1239 #ifdef MC6809 /* temp use pull strings to keep old order */
1241 regptr
= regpulllist
;
1242 lastregbit
= 1 << 7;
1245 separator
= OPSEPARATOR
;
1251 if (regbit
& reglist
)
1255 if (*regptr
!= FLAGSREGCHAR
)
1263 while (*regptr
>= MINREGCHAR
);
1264 bytespushed
+= *regptr
++ - '0';
1269 separator
= OPERANDSEPARATOR
;
1275 while (*regptr
++ >= MINREGCHAR
);
1276 if (regbit
== lastregbit
)
1278 #ifdef MC6809 /* temp use pull strings to keep old order */
1280 #else /* this should normally be unconditional */
1281 if ((bool_t
) pushflag
)
1293 PUBLIC
void pushreg(reg
)
1302 PUBLIC
void storereg(sourcereg
, target
)
1304 struct symstruct
*target
;
1308 if (target
->indcount
== 0)
1310 if (target
->offset
.offi
!= 0 || target
->level
== OFFKLUDGELEVEL
||
1311 !(target
->storage
& allregs
) || target
->storage
& CHARREGS
)
1312 bugerror("bad register store");
1313 else if ((store_t
) (targreg
= target
->storage
) != (store_t
) sourcereg
)
1315 target
->storage
= sourcereg
;
1316 loadadr(target
, targreg
); /* do LEA or TFR */
1322 /* Added acess to CPU registers. Just declare _AX etc. as
1323 * extern int, and you can use them to get/set
1324 * the register values. (vak) */
1325 if (target
->storage
== GLOBAL
&& !(target
->flags
& LABELLED
) &&
1326 *target
->name
.namep
!= 0 &&
1327 strncmp(target
->name
.namep
, "__", 2) == 0)
1329 if (strcmp (target
->name
.namep
, "__AX") == 0) { return; }
1330 if (strcmp (target
->name
.namep
, "__BX") == 0) { outstr ("mov\tbx,"); outregname(sourcereg
); outnl(); return; }
1331 if (strcmp (target
->name
.namep
, "__CX") == 0) { outstr ("mov\tcx,"); outregname(sourcereg
); outnl(); return; }
1332 if (strcmp (target
->name
.namep
, "__DX") == 0) { outstr ("mov\tdx,"); outregname(sourcereg
); outnl(); return; }
1333 if (strcmp (target
->name
.namep
, "__SP") == 0) { outstr ("mov\tsp,"); outregname(sourcereg
); outnl(); return; }
1334 if (strcmp (target
->name
.namep
, "__BP") == 0) { outstr ("mov\tbp,"); outregname(sourcereg
); outnl(); return; }
1335 if (strcmp (target
->name
.namep
, "__SI") == 0) { outstr ("mov\tsi,"); outregname(sourcereg
); outnl(); return; }
1336 if (strcmp (target
->name
.namep
, "__DI") == 0) { outstr ("mov\tdi,"); outregname(sourcereg
); outnl(); return; }
1337 if (strcmp (target
->name
.namep
, "__CS") == 0) { outstr ("mov\tcs,"); outregname(sourcereg
); outnl(); return; }
1338 if (strcmp (target
->name
.namep
, "__DS") == 0) { outstr ("mov\tds,"); outregname(sourcereg
); outnl(); return; }
1339 if (strcmp (target
->name
.namep
, "__ES") == 0) { outstr ("mov\tes,"); outregname(sourcereg
); outnl(); return; }
1340 if (strcmp (target
->name
.namep
, "__SS") == 0) { outstr ("mov\tss,"); outregname(sourcereg
); outnl(); return; }
1341 if (strcmp (target
->name
.namep
, "__FLAGS") == 0) { outstr ("push\tax"); outregname(sourcereg
); outstr ("\npopf\n"); return; }
1346 if (target
->storage
== GLOBAL
&& (store_t
) sourcereg
& (AXREG
| ALREG
))
1351 if (i386_32
&& target
->type
->scalar
& SHORT
)
1353 outshortregname(sourcereg
);
1359 outnregname(sourcereg
);
1362 if ((store_t
) sourcereg
== YREG
)
1364 outregname(sourcereg
);
1370 /*-----------------------------------------------------------------------------
1371 struc(element leaf, structure leaf)
1372 evaluates the expression
1374 -----------------------------------------------------------------------------*/
1376 PUBLIC
void struc(source
, target
)
1377 struct symstruct
*source
;
1378 struct symstruct
*target
;
1381 if (source
->offset
.offi
!= 0 || source
->level
== OFFKLUDGELEVEL
)
1383 if (target
->indcount
!= 0 || target
->level
== OFFKLUDGELEVEL
)
1384 load(target
, getindexreg());
1385 target
->offset
.offi
+= source
->offset
.offi
;
1387 if (source
->indcount
== 0)
1388 target
->type
= source
->type
;
1391 target
->type
= pointype(source
->type
); /* lost by = */
1396 PUBLIC
void transfer(source
, targreg
)
1397 struct symstruct
*source
;
1400 regtransfer(source
->storage
, targreg
);
1401 source
->storage
= targreg
;