annotate lwasm/insn_rel.c @ 506:7e8298f7bc0a

Add basic syntax for typecasting Add parser support for type casts. This current scheme handles only integer types. Also include parenthesis grouping in expressions.
author William Astle <lost@l-w.ca>
date Sun, 27 Oct 2019 12:06:01 -0600
parents cad5937314cb
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
1 /*
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
2 insn_rel.c
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
3 Copyright © 2009 William Astle
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
4
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
5 This file is part of LWASM.
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
6
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
7 LWASM is free software: you can redistribute it and/or modify it under the
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
8 terms of the GNU General Public License as published by the Free Software
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
9 Foundation, either version 3 of the License, or (at your option) any later
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
10 version.
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
11
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
12 This program is distributed in the hope that it will be useful, but WITHOUT
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
15 more details.
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
16
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
17 You should have received a copy of the GNU General Public License along with
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
18 this program. If not, see <http://www.gnu.org/licenses/>.
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
19 */
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
20
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
21 /*
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
22 for handling relative mode instructions
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
23 */
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
24
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
25 #include <ctype.h>
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
26 #include <stdlib.h>
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
27 #include <stdio.h>
377
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
28 #include <string.h>
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
29
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
30 #include <lw_expr.h>
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
31
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
32 #include "lwasm.h"
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
33 #include "instab.h"
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
34
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
35 /*
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
36 For generic relative, the first "opcode" is the natural opcode for the
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
37 mneumonic. The second "opcode" is the natural size of the relative offset.
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
38 These will be used when pragma autobranchlength is NOT in effect.
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
39
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
40 The third "opcode" is the short (8 bit) version of the branch. The final one
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
41 is the long (16 bit) version of the branch. These will be used when pragma
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
42 autobranchlength is in effect.
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
43
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
44 When autobranchlength is in effect, the branch target can be prefixed with
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
45 either < or > to force a short or long branch. Note that in this mode,
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
46 a > or < on its own still specifies a branch point.
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
47
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
48 */
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
49 PARSEFUNC(insn_parse_relgen)
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
50 {
377
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
51 lw_expr_t t = NULL, e1, e2;
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
52
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
53 l -> lint = -1;
211
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
54 l -> maxlen = OPLEN(instab[l -> insn].ops[3]) + 2;
241
d0e9dbe9afbe Add new heuristic for resolving instruction sizes.
William Astle <lost@l-w.ca>
parents: 211
diff changeset
55 l -> minlen = OPLEN(instab[l -> insn].ops[2]) + 1;
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
56 if (CURPRAGMA(l, PRAGMA_AUTOBRANCHLENGTH) == 0)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
57 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
58 l -> lint = instab[l -> insn].ops[1];
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
59 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
60 else
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
61 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
62 if (**p == '>' && (((*p)[1]) && !isspace((*p)[1])))
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
63 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
64 (*p)++;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
65 l -> lint = 16;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
66 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
67 else if (**p == '<' && (((*p)[1]) && !isspace((*p)[1])))
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
68 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
69 (*p)++;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
70 l -> lint = 8;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
71 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
72 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
73
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
74 /* forced sizes handled */
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
75
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
76 // sometimes there is a "#", ignore if there
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
77 if (**p == '#')
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
78 (*p)++;
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
79
377
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
80 if (CURPRAGMA(l, PRAGMA_QRTS))
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
81 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
82 // handle ?RTS conditional return
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
83 if (**p == '?')
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
84 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
85 if (strncasecmp(*p, "?RTS", 4) == 0)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
86 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
87 (*p) += 4;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
88
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
89 line_t *cl = l;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
90 for (cl = cl->prev; cl; cl = cl->prev)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
91 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
92 if (cl->insn == -1)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
93 continue;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
94
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
95 if (l->addr->value - cl->addr->value > 128)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
96 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
97 cl = NULL;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
98 break;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
99 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
100
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
101 if (cl->conditional_return)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
102 break;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
103
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
104 if (instab[cl->insn].ops[0] == 0x39)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
105 break;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
106 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
107
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
108 if (cl)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
109 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
110 l->lint = -1;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
111 if (cl->conditional_return)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
112 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
113 e2 = lw_expr_build(lw_expr_type_special, lwasm_expr_lineaddr, cl);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
114 e1 = lw_expr_build(lw_expr_type_int, 2);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
115 t = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, e1, e2);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
116 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
117 else
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
118 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
119 t = lw_expr_build(lw_expr_type_special, lwasm_expr_lineaddr, cl);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
120 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
121 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
122 else
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
123 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
124 l->conditional_return = 1;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
125
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
126 // t = * + 1
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
127
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
128 e2 = lw_expr_build(lw_expr_type_special, lwasm_expr_lineaddr, l);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
129 e1 = lw_expr_build(lw_expr_type_int, 1);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
130 t = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, e1, e2);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
131
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
132 lw_expr_destroy(e1);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
133 lw_expr_destroy(e2);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
134 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
135 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
136 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
137 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
138
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
139 if (!t)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
140 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
141 t = lwasm_parse_expr(as, p);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
142 }
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
143
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
144 if (!t)
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
145 {
370
8764142b3192 Convert internal error/warning handling framework to a new unified system
William Astle <lost@l-w.ca>
parents: 241
diff changeset
146 lwasm_register_error(as, l, E_OPERAND_BAD);
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
147 return;
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
148 }
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
149
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
150 // if we know the length of the instruction, set it now
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
151 if (l -> lint == 8)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
152 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
153 l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
377
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
154 if (l->conditional_return) l->len++;
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
155 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
156 else if (l -> lint == 16)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
157 {
122
2be2649841f8 Fixed embarrassing off by one in insn_rel length calculation
lost@l-w.ca
parents: 116
diff changeset
158 l -> len = OPLEN(instab[l -> insn].ops[3]) + 2;
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
159 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
160
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
161 // the offset calculation here depends on the length of this line!
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
162 // how to calculate requirements?
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
163 // this is the same problem faced by ,pcr indexing
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
164 e2 = lw_expr_build(lw_expr_type_special, lwasm_expr_linelen, l);
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
165 e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, t, e2);
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
166 lw_expr_destroy(e2);
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
167 e2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_minus, e1, l -> addr);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
168 lw_expr_destroy(e1);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
169 lwasm_save_expr(l, 0, e2);
89
651b85a98c1b Fixed memory leaks revealed by valgrind
lost@l-w.ca
parents: 2
diff changeset
170 lw_expr_destroy(t);
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
171
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
172 if (l -> len == -1)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
173 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
174 e1 = lw_expr_copy(e2);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
175 l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
176 lwasm_reduce_expr(as, e1);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
177 l -> len = -1;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
178 if (lw_expr_istype(e1, lw_expr_type_int))
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
179 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
180 int v;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
181 v = lw_expr_intval(e1);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
182 if (v >= -128 && v <= 127)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
183 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
184 l -> lint = 8;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
185 l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
186 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
187 else
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
188 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
189 l -> lint = 16;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
190 l -> len = OPLEN(instab[l -> insn].ops[3]) + 2;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
191 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
192 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
193 lw_expr_destroy(e1);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
194 }
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
195 }
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
196
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
197 RESOLVEFUNC(insn_resolve_relgen)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
198 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
199 lw_expr_t e, e2;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
200 int offs;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
201
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
202 if (l -> lint == -1)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
203 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
204 e = lwasm_fetch_expr(l, 0);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
205 if (!lw_expr_istype(e, lw_expr_type_int))
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
206 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
207 // temporarily set the instruction length to see if we get a
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
208 // constant for our expression; if so, we can select an instruction
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
209 // size
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
210 e2 = lw_expr_copy(e);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
211 // size of 8-bit opcode + 8 bit offset
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
212 l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
213 lwasm_reduce_expr(as, e2);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
214 l -> len = -1;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
215 if (lw_expr_istype(e2, lw_expr_type_int))
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
216 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
217 // it reduced to an integer; is it in 8 bit range?
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
218 offs = lw_expr_intval(e2);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
219 if (offs >= -128 && offs <= 127)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
220 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
221 // fits in 8 bits
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
222 l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
223 l -> lint = 8;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
224 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
225 else
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
226 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
227 // requires 16 bits
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
228 l -> len = OPLEN(instab[l -> insn].ops[3]) + 2;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
229 l -> lint = 16;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
230 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
231 }
211
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
232 // size of 8-bit opcode + 8 bit offset
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
233 l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
234 as -> pretendmax = 1;
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
235 lwasm_reduce_expr(as, e2);
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
236 as -> pretendmax = 0;
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
237 l -> len = -1;
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
238 if (lw_expr_istype(e2, lw_expr_type_int))
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
239 {
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
240 // it reduced to an integer; is it in 8 bit range?
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
241 offs = lw_expr_intval(e2);
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
242 if (offs >= -128 && offs <= 127)
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
243 {
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
244 // fits in 8 bits with a worst case scenario
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
245 l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
246 l -> lint = 8;
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
247 }
6f2e18f1fe67 Improve autobranchlength pragma
William Astle <lost@l-w.ca>
parents: 122
diff changeset
248 }
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
249 lw_expr_destroy(e2);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
250 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
251 if (lw_expr_istype(e, lw_expr_type_int))
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
252 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
253 // it reduced to an integer; is it in 8 bit range?
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
254 offs = lw_expr_intval(e);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
255 if (offs >= -128 && offs <= 127)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
256 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
257 // fits in 8 bits
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
258 l -> len = OPLEN(instab[l -> insn].ops[2]) + 1;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
259 l -> lint = 8;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
260 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
261 else
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
262 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
263 // requires 16 bits
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
264 l -> len = OPLEN(instab[l -> insn].ops[3]) + 2;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
265 l -> lint = 16;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
266 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
267 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
268 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
269 if (!force)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
270 return;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
271
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
272 if (l -> len == -1)
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
273 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
274 l -> len = OPLEN(instab[l -> insn].ops[3]) + 2;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
275 l -> lint = 16;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
276 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
277 }
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
278
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
279 EMITFUNC(insn_emit_relgen)
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
280 {
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
281 lw_expr_t e;
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
282 int offs;
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
283
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
284 e = lwasm_fetch_expr(l, 0);
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
285 if (l -> lint == 8)
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
286 {
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
287 if (!lw_expr_istype(e, lw_expr_type_int))
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
288 {
370
8764142b3192 Convert internal error/warning handling framework to a new unified system
William Astle <lost@l-w.ca>
parents: 241
diff changeset
289 lwasm_register_error(as, l, E_EXPRESSION_NOT_CONST);
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
290 return;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
291 }
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
292
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
293 offs = lw_expr_intval(e);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
294 if (l -> lint == 8 && (offs < -128 || offs > 127))
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
295 {
370
8764142b3192 Convert internal error/warning handling framework to a new unified system
William Astle <lost@l-w.ca>
parents: 241
diff changeset
296 lwasm_register_error(as, l, E_BYTE_OVERFLOW);
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
297 return;
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
298 }
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
299
377
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
300 if (l->conditional_return)
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
301 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
302 lwasm_emitop(l, instab[l->insn].ops[2] ^ 1); /* flip branch, add RTS */
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
303 lwasm_emit(l, 1);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
304 lwasm_emit(l, 0x39);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
305 l->cycle_adj = 3;
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
306 }
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
307 else
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
308 {
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
309 lwasm_emitop(l, instab[l->insn].ops[2]);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
310 lwasm_emit(l, offs);
67373a053c49 Add ?rts target for branch instructions
William Astle <lost@l-w.ca>
parents: 376
diff changeset
311 }
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
312 }
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
313 else
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
314 {
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
315 lwasm_emitop(l, instab[l -> insn].ops[3]);
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
316 lwasm_emitexpr(l, e, 2);
455
cad5937314cb Add operandsizewarning pragma
William Astle <lost@l-w.ca>
parents: 408
diff changeset
317 if (CURPRAGMA(l, PRAGMA_OPERANDSIZE) && lw_expr_istype(e, lw_expr_type_int))
cad5937314cb Add operandsizewarning pragma
William Astle <lost@l-w.ca>
parents: 408
diff changeset
318 {
cad5937314cb Add operandsizewarning pragma
William Astle <lost@l-w.ca>
parents: 408
diff changeset
319 offs = lw_expr_intval(e);
cad5937314cb Add operandsizewarning pragma
William Astle <lost@l-w.ca>
parents: 408
diff changeset
320 if (offs >= -128 && offs <= 127)
cad5937314cb Add operandsizewarning pragma
William Astle <lost@l-w.ca>
parents: 408
diff changeset
321 {
cad5937314cb Add operandsizewarning pragma
William Astle <lost@l-w.ca>
parents: 408
diff changeset
322 lwasm_register_error(as, l, W_OPERAND_SIZE);
cad5937314cb Add operandsizewarning pragma
William Astle <lost@l-w.ca>
parents: 408
diff changeset
323 }
cad5937314cb Add operandsizewarning pragma
William Astle <lost@l-w.ca>
parents: 408
diff changeset
324 }
116
7b0716264251 Pragma autobranchlength implementation completed
lost@l-w.ca
parents: 91
diff changeset
325 }
0
2c24602be78f Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
lost@l-w.ca
parents:
diff changeset
326 }