1/*****************************************************************************/
2/* */
3/* easw16.c */
4/* */
5/* SWEET16 effective address parsing for the ca65 macroassembler */
6/* */
7/* */
8/* */
9/* (C) 2004-2011, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* */
15/* This software is provided 'as-is', without any expressed or implied */
16/* warranty. In no event will the authors be held liable for any damages */
17/* arising from the use of this software. */
18/* */
19/* Permission is granted to anyone to use this software for any purpose, */
20/* including commercial applications, and to alter it and redistribute it */
21/* freely, subject to the following restrictions: */
22/* */
23/* 1. The origin of this software must not be misrepresented; you must not */
24/* claim that you wrote the original software. If you use this software */
25/* in a product, an acknowledgment in the product documentation would be */
26/* appreciated but is not required. */
27/* 2. Altered source versions must be plainly marked as such, and must not */
28/* be misrepresented as being the original software. */
29/* 3. This notice may not be removed or altered from any source */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36/* ca65 */
37#include "ea.h"
38#include "ea65.h"
39#include "error.h"
40#include "expr.h"
41#include "instr.h"
42#include "nexttok.h"
43
44
45
46/*****************************************************************************/
47/* Code */
48/*****************************************************************************/
49
50
51
52static long RegNum ()
53/* Try to read a register number specified not as a register (Rx) but as a
54** numeric value between 0 and 15. Return the register number or -1 on
55** failure.
56*/
57{
58 long Val;
59 ExprNode* Expr = Expression ();
60 if (!IsConstExpr (Expr, &Val) || Val < 0 || Val > 15) {
61 /* Invalid register */
62 Val = -1L;
63 }
64
65 /* Free the expression and return the register number */
66 FreeExpr (Expr);
67 return Val;
68}
69
70
71
72void GetSweet16EA (EffAddr* A)
73/* Parse an effective address, return the result in A */
74{
75 long Reg;
76
77 /* Clear the output struct */
78 A->AddrModeSet = 0;
79 A->Expr = 0;
80 A->Reg = 0;
81
82 /* Parse the effective address */
83 if (TokIsSep (CurTok.Tok)) {
84
85 A->AddrModeSet = AMSW16_IMP;
86
87 } else if (CurTok.Tok == TOK_AT) {
88
89 /* @reg or @regnumber */
90 A->AddrModeSet = AMSW16_IND;
91 NextTok ();
92 if (CurTok.Tok == TOK_REG) {
93 A->Reg = (unsigned) CurTok.IVal;
94 NextTok ();
95 } else if ((Reg = RegNum ()) >= 0) {
96 /* Register number */
97 A->Reg = (unsigned) Reg;
98 } else {
99 ErrorSkip ("Register or register number expected");
100 A->Reg = 0;
101 }
102
103 } else if (CurTok.Tok == TOK_REG) {
104
105 A->Reg = (unsigned) CurTok.IVal;
106 NextTok ();
107
108 if (CurTok.Tok == TOK_COMMA) {
109
110 /* Rx, constant */
111 NextTok ();
112 A->Expr = Expression ();
113
114 A->AddrModeSet = AMSW16_IMM;
115
116 } else {
117
118 A->AddrModeSet = AMSW16_REG;
119
120 }
121
122 } else {
123
124 /* OPC ea or: OPC regnum, constant */
125 A->Expr = Expression ();
126 A->AddrModeSet = AMSW16_BRA;
127
128 /* If the value is a constant between 0 and 15, it may also be a
129 ** register number.
130 */
131 if (IsConstExpr (A->Expr, &Reg) && Reg >= 0 && Reg <= 15) {
132 FreeExpr (A->Expr);
133 A->Reg = (unsigned) Reg;
134
135 /* If a comma follows, it is: OPC Rx, constant */
136 if (CurTok.Tok == TOK_COMMA) {
137 NextTok ();
138 A->Expr = Expression ();
139 A->AddrModeSet = AMSW16_IMM;
140 } else {
141 A->Expr = 0;
142 A->AddrModeSet |= AMSW16_REG;
143 }
144 }
145
146 }
147}
148
149
150
151