summaryrefslogtreecommitdiff
path: root/bcc/reg.h
blob: 822bda7b3d3da4d0162cea4717eba0f7855a06c8 (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* reg.h - registers for bcc */

/* Copyright (C) 1992 Bruce Evans */

/*
  The compiler generates "addresses" of the form
      indirect(indcount) (rx + offset)
  where
      rx is a machine register (possibly null)
      n is the indirection count (possibly 0)
      offset is a constant.
  It does not support more complicated formats like
      indirect(indcount) (rx + index * scale + offset).

      The register is coded as bit flag in the  storage  component of
  the symbol structure. This allows groups of registers to be tested
  using bitwise "&". Throughout the compiler, the group of these bit
  flags has the type  reg_t. If there are only a few registers, reg_t
  can be an unsigned char. It must be unsigned if the high bit is
  used, to avoid sign extension problems. For bootstrapping the compiler
  from a compiler with no unsigned char, the unsigned type should be
  used instead (with a signifigant waste of storage).

      The bit flags should really be defined as ((reg_t) whatever) but
  then they would not (necessarily) be constant expressions and couldn't
  be used in switch selectors or (worse) preprocessor expressions.

      The CONSTANT and GLOBAL (non-) register bits are almost
  equivalent. A constant with nonzero indirection is marked as a
  GLOBAL and not a CONSTANT. This makes it easier to test for a constant
  CONSTANT. Globals which are formed in this way are converted to
  constants if their indirection count is reset to 0 (by & operator).
*/

/* register bit flags */

#define NOSTORAGE 0x000		/* structure/union member offsets */
#define CONSTANT  0x001		/* offsets are values */
#define BREG      0x002
#define DREG      0x004
#define INDREG0   0x008
#define INDREG1   0x010
#define INDREG2   0x020
#define LOCAL     0x040
#define GLOBAL    0x080		/* offsets from storage name or 0 */
#define CCREG     CONSTANT	/* arg to PSHS/PULS functions only */
#ifdef I8088
# ifdef FRAMEPOINTER
#  define FRAMEREG LOCAL
# endif
# define STACKREG 0x100
# define DATREG1  0x200
# define DATREG2  0x400
# define DATREG1B 0x800
#endif
#ifdef MC6809
# define DPREG    LOCAL		/* arg to PSHS/PULS functions only */
# define PCREG    GLOBAL	/* arg to PSHS/PULS functions only */
#endif

/* data for pushing and pulling registers */

#define MINREGCHAR 'A'
#ifdef I8088
# define FLAGSREGCHAR 'f'
# define pushchar() pushlist(AXREG)
#endif
#ifdef MC6809
# define pushchar() pushlist(BREG)
#endif

/* special registers */

#ifdef I8088
# define ALREG    BREG
# define AXREG    DREG
# define DXREG    DATREG2
# define MULREG   DATREG1B
# define SHIFTREG DATREG1B
#endif
#ifdef MC6809
# define XREG INDREG0		/* XREG is special for ABX in index & switch */
# define YREG INDREG2		/* XREG and YREG allow LEA (Z test) in cmp() */
#endif

/* groups of registers */

#define ALLDATREGS (BREG|DREG)
#define CHARREGS BREG
#define MAXREGS 1		/* number of data registers */
#define WORKDATREGS (BREG|DREG)

/* function call and return registers */

#define ARGREG RETURNREG	/* for (1st) argument */
#define LONGARGREGS LONGRETURNREGS	/* for long or float arg */
#define LONGRETURNREGS (INDREG0|LONGREG2)
#define LONGREG2 DREG
#ifdef I8088
# define LONGRETSPECIAL	/* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
# define RETURNREG DREG
#endif
#ifdef MC6809
# define RETURNREG INDREG0
#endif

/* registers which can be pulled as a group with the program counter */
/* to perform an efficient function return */

#ifdef MC6809
#define JUNK1REGS BREG		/* 1 bytes locals to discard */
#define JUNK2REGS INDREG2
#define JUNK3REGS (BREG|INDREG2)
#define JUNK4REGS (INDREG1|INDREG2)
#endif

/* registers which can be pushed as a group with the first argument */
/* to perform an efficient function startup */

#ifdef MC6809
# define LOC1REGS CCREG		/* 1 bytes local to allocate */
# define LOC2REGS DREG
# define LOC3REGS (CCREG|DREG)
# define LOC4REGS (CCREG|DREG|DPREG)
# endif

/* registers to be used by software operations */

#define OPREG INDREG0		/* 2nd reg for software ops (1st is DREG) */
#define OPWORKREG INDREG2	/* 3rd register for software ops */

/* maximum indirection count for 1 instruction */

#ifdef I8088
# define MAXINDIRECT 1
#endif
#ifdef MC6809
# define MAXINDIRECT 2
#endif