~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Source/Core/Core/Src/DSP/assemble.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*====================================================================
 
2
 
 
3
$Id: assemble.cpp,v 1.3 2008-11-11 01:04:26 wntrmute Exp $
 
4
 
 
5
project:      GameCube DSP Tool (gcdsp)
 
6
mail:             duddie@walla.com
 
7
 
 
8
Copyright (c) 2005 Duddie
 
9
 
 
10
This program is free software; you can redistribute it and/or
 
11
modify it under the terms of the GNU General Public License
 
12
as published by the Free Software Foundation; either version 2
 
13
of the License, or (at your option) any later version.
 
14
 
 
15
This program is distributed in the hope that it will be useful,
 
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
GNU General Public License for more details.
 
19
 
 
20
You should have received a copy of the GNU General Public License
 
21
along with this program; if not, write to the Free Software
 
22
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
23
 
 
24
Revision 1.4  2008/10/04 10:30:00  Hermes
 
25
added function to export the code to .h file
 
26
added support for '/ *' '* /' and '//' for comentaries
 
27
added some sintax detection when use registers
 
28
 
 
29
$Log: not supported by cvs2svn $
 
30
Revision 1.2  2005/09/14 02:19:29  wntrmute
 
31
added header guards
 
32
use standard main function
 
33
 
 
34
Revision 1.1  2005/08/24 22:13:34  wntrmute
 
35
Initial import
 
36
 
 
37
 
 
38
====================================================================*/
 
39
 
 
40
#include <cstdio>
 
41
#include <cstdlib>
 
42
 
 
43
#include <map>
 
44
#include <iostream>
 
45
#include <fstream>
 
46
 
 
47
#include "Common.h"
 
48
#include "FileUtil.h"
 
49
#include "DSPInterpreter.h"
 
50
#include "DSPTables.h"
 
51
#include "disassemble.h"
 
52
#include "assemble.h"
 
53
 
 
54
static const char *err_string[] =
 
55
{
 
56
        "",
 
57
        "Unknown Error",
 
58
        "Unknown opcode",
 
59
        "Not enough parameters",
 
60
        "Too many parameters",
 
61
        "Wrong parameter",
 
62
        "Expected parameter of type 'string'",
 
63
        "Expected parameter of type 'value'",
 
64
        "Expected parameter of type 'register'",
 
65
        "Expected parameter of type 'memory pointer'",
 
66
        "Expected parameter of type 'immediate'",
 
67
        "Incorrect binary value",
 
68
        "Incorrect hexadecimal value",
 
69
        "Incorrect decimal value",
 
70
        "Label already exists",
 
71
        "Label not defined",
 
72
        "No matching brackets",
 
73
        "This opcode cannot be extended",
 
74
        "Given extending params for non extensible opcode",
 
75
        "Wrong parameter: must be accumulator register",
 
76
        "Wrong parameter: must be mid accumulator register",
 
77
        "Invalid register",
 
78
        "Number out of range"
 
79
};
 
80
 
 
81
DSPAssembler::DSPAssembler(const AssemblerSettings &settings) : 
 
82
        gdg_buffer(NULL),
 
83
        m_cur_addr(0),
 
84
        m_cur_pass(0),
 
85
        m_current_param(0),
 
86
        settings_(settings)
 
87
 
 
88
{
 
89
}
 
90
 
 
91
DSPAssembler::~DSPAssembler()
 
92
{
 
93
        if(gdg_buffer)
 
94
                free(gdg_buffer);
 
95
}
 
96
 
 
97
bool DSPAssembler::Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers)
 
98
{
 
99
        if (line_numbers)
 
100
                line_numbers->clear();
 
101
        const char *fname = "tmp.asm";
 
102
        if (!File::WriteStringToFile(true, text, fname))
 
103
                return false;
 
104
        InitPass(1);
 
105
        if (!AssembleFile(fname, 1))
 
106
                return false;
 
107
 
 
108
        // We now have the size of the output buffer
 
109
        if (m_totalSize > 0)
 
110
        {
 
111
                gdg_buffer = (char *)malloc(m_totalSize * sizeof(u16) + 4);
 
112
                if(!gdg_buffer)
 
113
                        return false;
 
114
 
 
115
                memset(gdg_buffer, 0, m_totalSize * sizeof(u16));
 
116
        } else
 
117
                return false;
 
118
 
 
119
        InitPass(2);
 
120
        if (!AssembleFile(fname, 2))
 
121
                return false;
 
122
 
 
123
        code.resize(m_totalSize);
 
124
        for (int i = 0; i < m_totalSize; i++) {
 
125
                code[i] = *(u16 *)(gdg_buffer + i * 2);
 
126
        }
 
127
 
 
128
        if(gdg_buffer) {
 
129
                free(gdg_buffer);
 
130
                gdg_buffer = NULL;
 
131
        }
 
132
 
 
133
        last_error_str = "(no errors)";
 
134
        last_error = ERR_OK;
 
135
 
 
136
        return true;
 
137
}
 
138
 
 
139
void DSPAssembler::ShowError(err_t err_code, const char *extra_info)
 
140
{
 
141
 
 
142
        if (!settings_.force)
 
143
                failed = true;
 
144
 
 
145
        char error_buffer[1024];
 
146
        char *buf_ptr = error_buffer;
 
147
        buf_ptr += sprintf(buf_ptr, "%i : %s ", code_line, cur_line.c_str());
 
148
        if (!extra_info)
 
149
                extra_info = "-";
 
150
 
 
151
        if (m_current_param == 0)
 
152
                buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d : %s\n", err_string[err_code], code_line, extra_info);
 
153
        else 
 
154
                buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d Param: %d : %s\n",
 
155
                                                   err_string[err_code], code_line, m_current_param, extra_info);
 
156
        last_error_str = error_buffer;
 
157
        last_error = err_code;
 
158
}
 
159
 
 
160
char *skip_spaces(char *ptr)
 
161
{
 
162
        while (*ptr == ' ')
 
163
                ptr++;
 
164
        return ptr;
 
165
}
 
166
 
 
167
const char *skip_spaces(const char *ptr)
 
168
{
 
169
        while (*ptr == ' ')
 
170
                ptr++;
 
171
        return ptr;
 
172
}
 
173
 
 
174
// Parse a standalone value - it can be a number in one of several formats or a label.
 
175
s32 DSPAssembler::ParseValue(const char *str)
 
176
{
 
177
        bool negative = false;
 
178
        s32 val = 0;
 
179
        const char *ptr = str;
 
180
 
 
181
        if (ptr[0] == '#')
 
182
        {
 
183
                ptr++;
 
184
                negative = true;  // Wow! Double # (needed one to get in here) negates???
 
185
        }
 
186
        if (ptr[0] == '-')
 
187
        {
 
188
                ptr++;
 
189
                negative = true;
 
190
        }
 
191
        if (ptr[0] == '0')
 
192
        {
 
193
                if (ptr[1] >= '0' && ptr[1] <= '9')
 
194
                {
 
195
                        for (int i = 0; ptr[i] != 0; i++)
 
196
                        {
 
197
                                val *= 10;
 
198
                                if (ptr[i] >= '0' && ptr[i] <= '9')
 
199
                                        val += ptr[i] - '0';
 
200
                                else
 
201
                                        ShowError(ERR_INCORRECT_DEC, str);
 
202
                        }
 
203
                }
 
204
                else
 
205
                {
 
206
                        switch (ptr[1])
 
207
                        {
 
208
                        case 'X': // hex
 
209
                                for (int i = 2 ; ptr[i] != 0 ; i++)
 
210
                                {
 
211
                                        val <<= 4;
 
212
                                        if (ptr[i] >= 'a' && ptr[i] <= 'f')
 
213
                                                val += (ptr[i]-'a'+10);
 
214
                                        else if (ptr[i] >= 'A' && ptr[i] <= 'F')
 
215
                                                val += (ptr[i]-'A'+10);
 
216
                                        else if (ptr[i] >= '0' && ptr[i] <= '9')
 
217
                                                val += (ptr[i] - '0');
 
218
                                        else
 
219
                                                ShowError(ERR_INCORRECT_HEX, str);
 
220
                                }
 
221
                                break;
 
222
                        case '\'': // binary
 
223
                                for (int i = 2; ptr[i] != 0; i++)
 
224
                                {
 
225
                                        val *=2;
 
226
                                        if(ptr[i] >= '0' && ptr[i] <= '1')
 
227
                                                val += ptr[i] - '0';
 
228
                                        else
 
229
                                                ShowError(ERR_INCORRECT_BIN, str);
 
230
                                }
 
231
                                break;
 
232
                        default:
 
233
                                // value is 0 or error
 
234
                                val = 0;
 
235
                                break;
 
236
                        }
 
237
                }
 
238
        }
 
239
        else
 
240
        {
 
241
                // Symbol starts with a digit - it's a dec number.
 
242
                if (ptr[0] >= '0' && ptr[0] <= '9')
 
243
                {
 
244
                        for (int i = 0; ptr[i] != 0; i++)
 
245
                        {
 
246
                                val *= 10;
 
247
                                if (ptr[i] >= '0' && ptr[i] <= '9')
 
248
                                        val += ptr[i] - '0';
 
249
                                else
 
250
                                        ShowError(ERR_INCORRECT_DEC, str);
 
251
                        }
 
252
                }
 
253
                else  // Everything else is a label.
 
254
                {
 
255
                        // Lookup label
 
256
                        u16 value;
 
257
                        if (labels.GetLabelValue(ptr, &value))
 
258
                                return value;
 
259
                        if (m_cur_pass == 2)
 
260
                                ShowError(ERR_UNKNOWN_LABEL, str);
 
261
                }
 
262
        }
 
263
        if (negative)
 
264
                return -val;
 
265
        return val;
 
266
}
 
267
 
 
268
// Modifies both src and dst!
 
269
// What does it do, really??
 
270
char *DSPAssembler::FindBrackets(char *src, char *dst)
 
271
{
 
272
        s32 len = (s32) strlen(src);
 
273
        s32 first = -1;
 
274
        s32 count = 0;
 
275
        s32 i, j;
 
276
        j = 0;
 
277
        for (i = 0 ; i < len ; i++)
 
278
        {
 
279
                if (src[i] == '(')
 
280
                {
 
281
                        if (first < 0)
 
282
                        {
 
283
                                count = 1;
 
284
                                src[i] = 0x0;
 
285
                                first = i;
 
286
                        }
 
287
                        else
 
288
                        {
 
289
                                count++;
 
290
                                dst[j++] = src[i];
 
291
                        }
 
292
                }
 
293
                else if (src[i] == ')')
 
294
                {
 
295
                        if (--count == 0)
 
296
                        {
 
297
                                dst[j] = 0;
 
298
                                return &src[i+1];
 
299
                        }
 
300
                        else
 
301
                        {
 
302
                                dst[j++] = src[i];
 
303
                        }
 
304
                }
 
305
                else
 
306
                {
 
307
                        if (first >= 0)
 
308
                                dst[j++] = src[i];
 
309
                }
 
310
        }
 
311
        if (count)
 
312
                ShowError(ERR_NO_MATCHING_BRACKETS);
 
313
        return NULL;
 
314
}
 
315
 
 
316
// Bizarre in-place expression evaluator.
 
317
u32 DSPAssembler::ParseExpression(const char *ptr)
 
318
{
 
319
        char *pbuf;
 
320
        s32 val = 0;
 
321
 
 
322
        char *d_buffer = (char *)malloc(1024);
 
323
        char *s_buffer = (char *)malloc(1024);
 
324
        strcpy(s_buffer, ptr);
 
325
 
 
326
        while ((pbuf = FindBrackets(s_buffer, d_buffer)) != NULL)
 
327
        {
 
328
                val = ParseExpression(d_buffer);
 
329
                sprintf(d_buffer, "%s%d%s", s_buffer, val, pbuf);
 
330
                strcpy(s_buffer, d_buffer);
 
331
        }
 
332
 
 
333
        int j = 0;
 
334
        for (int i = 0; i < ((s32)strlen(s_buffer) + 1) ; i++)
 
335
        {
 
336
                char c = s_buffer[i];
 
337
                if (c != ' ')
 
338
                        d_buffer[j++] = c;
 
339
        }
 
340
 
 
341
        for (int i = 0; i < ((s32)strlen(d_buffer) + 1) ; i++)
 
342
        {
 
343
                char c = d_buffer[i];
 
344
                if (c == '-')
 
345
                {
 
346
                        if (i == 0)
 
347
                                c = '#';
 
348
                        else
 
349
                        {
 
350
                                switch (d_buffer[i - 1])
 
351
                                {
 
352
                                case '/':
 
353
                                case '%':
 
354
                                case '*':
 
355
                                        c = '#';
 
356
                                }
 
357
                        }
 
358
                }
 
359
                d_buffer[i] = c;
 
360
        }
 
361
 
 
362
        while ((pbuf = strstr(d_buffer, "+")) != NULL)
 
363
        {
 
364
                *pbuf = 0x0;
 
365
                val = ParseExpression(d_buffer) + ParseExpression(pbuf+1);
 
366
                sprintf(d_buffer, "%d", val);
 
367
        }
 
368
 
 
369
        while ((pbuf = strstr(d_buffer, "-")) != NULL)
 
370
        {
 
371
                *pbuf = 0x0;
 
372
                val = ParseExpression(d_buffer) - ParseExpression(pbuf+1);
 
373
                if (val < 0)
 
374
                {
 
375
                        val = 0x10000 + (val & 0xffff); // ATTENTION: avoid a terrible bug!!! number cannot write with '-' in sprintf
 
376
                        fprintf(stderr, "WARNING: Number Underflow at Line: %d \n", code_line);
 
377
                }
 
378
                sprintf(d_buffer, "%d", val);
 
379
        }
 
380
 
 
381
        while ((pbuf = strstr(d_buffer, "*")) != NULL)
 
382
        {
 
383
                *pbuf = 0x0;
 
384
                val = ParseExpression(d_buffer) * ParseExpression(pbuf+1);
 
385
                sprintf(d_buffer, "%d", val);
 
386
        }
 
387
 
 
388
        while ((pbuf = strstr(d_buffer, "/")) != NULL)
 
389
        {
 
390
                *pbuf = 0x0;
 
391
                val = ParseExpression(d_buffer) / ParseExpression(pbuf+1);
 
392
                sprintf(d_buffer, "%d", val);
 
393
        }
 
394
 
 
395
        while ((pbuf = strstr(d_buffer, "|")) != NULL)
 
396
        {
 
397
                *pbuf = 0x0;
 
398
                val = ParseExpression(d_buffer) | ParseExpression(pbuf+1);
 
399
                sprintf(d_buffer, "%d", val);
 
400
        }
 
401
 
 
402
        while ((pbuf = strstr(d_buffer, "&")) != NULL)
 
403
        {
 
404
                *pbuf = 0x0;
 
405
                val = ParseExpression(d_buffer) & ParseExpression(pbuf+1);
 
406
                sprintf(d_buffer, "%d", val);
 
407
        }
 
408
 
 
409
        val = ParseValue(d_buffer);
 
410
        free(d_buffer);
 
411
        free(s_buffer);
 
412
        return val;
 
413
}
 
414
 
 
415
// Destroys parstr
 
416
u32 DSPAssembler::GetParams(char *parstr, param_t *par)
 
417
{
 
418
        u32 count = 0;
 
419
        char *tmpstr = skip_spaces(parstr);
 
420
        tmpstr = strtok(tmpstr, ",\x00");
 
421
        for (int i = 0; i < 10; i++)
 
422
        {
 
423
                if (tmpstr == NULL)
 
424
                        break;
 
425
                tmpstr = skip_spaces(tmpstr);
 
426
                if (strlen(tmpstr) == 0)
 
427
                        break;
 
428
                if (tmpstr)
 
429
                        count++;
 
430
                else
 
431
                        break;
 
432
 
 
433
                par[i].type = P_NONE;
 
434
                switch (tmpstr[0])
 
435
                {
 
436
                case '"':
 
437
                        par[i].str = strtok(tmpstr, "\"");
 
438
                        par[i].type = P_STR;
 
439
                        break;
 
440
                case '#':
 
441
                        par[i].val = ParseExpression(tmpstr + 1);
 
442
                        par[i].type = P_IMM;
 
443
                        break;
 
444
                case '@':
 
445
                        if (tmpstr[1] == '$')
 
446
                        {
 
447
                                par[i].val = ParseExpression(tmpstr + 2);
 
448
                                par[i].type = P_PRG;
 
449
                        }
 
450
                        else
 
451
                        {
 
452
                                par[i].val = ParseExpression(tmpstr + 1);
 
453
                                par[i].type = P_MEM;
 
454
                        }
 
455
                        break;
 
456
                case '$':
 
457
                        par[i].val = ParseExpression(tmpstr + 1);
 
458
                        par[i].type = P_REG;
 
459
                        break;
 
460
 
 
461
                default:
 
462
                        par[i].val = ParseExpression(tmpstr);
 
463
                        par[i].type = P_VAL;
 
464
                        break;
 
465
                }
 
466
                tmpstr = strtok(NULL, ",\x00");
 
467
        }
 
468
        return count;
 
469
}
 
470
 
 
471
const opc_t *DSPAssembler::FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size)
 
472
{
 
473
        if (opcode[0] == 'C' && opcode[1] == 'W')
 
474
                return &cw;
 
475
 
 
476
        AliasMap::const_iterator alias_iter = aliases.find(opcode);
 
477
        if (alias_iter != aliases.end())
 
478
                opcode = alias_iter->second.c_str();
 
479
        for (int i = 0; i < opcod_size; i++)
 
480
        {
 
481
                const opc_t *opc = &opcod[i];
 
482
                if (strcmp(opc->name, opcode) == 0)
 
483
                {
 
484
                        if (par_count < opc->param_count)
 
485
                        {
 
486
                                ShowError(ERR_NOT_ENOUGH_PARAMETERS);
 
487
                        }
 
488
                        if (par_count > opc->param_count)
 
489
                        {
 
490
                                ShowError(ERR_TOO_MANY_PARAMETERS);
 
491
                        }
 
492
                        return opc;
 
493
                }
 
494
        }
 
495
        ShowError(ERR_UNKNOWN_OPCODE);
 
496
        return NULL;
 
497
}
 
498
 
 
499
// weird...
 
500
u16 get_mask_shifted_down(u16 mask)
 
501
{
 
502
        while (!(mask & 1))
 
503
                mask >>= 1;
 
504
        return mask;
 
505
}
 
506
 
 
507
bool DSPAssembler::VerifyParams(const opc_t *opc, param_t *par, int count, bool ext)
 
508
{
 
509
        for (int i = 0; i < count; i++)
 
510
        {
 
511
                const int current_param = i + 1;  // just for display.
 
512
                if (opc->params[i].type != par[i].type || (par[i].type & P_REG))
 
513
                {
 
514
                        if (par[i].type == P_VAL &&
 
515
                                (opc->params[i].type == P_ADDR_I || opc->params[i].type == P_ADDR_D))
 
516
                        {
 
517
                                // Data and instruction addresses are valid as VAL values.
 
518
                                continue;
 
519
                        }
 
520
 
 
521
                        if ((opc->params[i].type & P_REG) && (par[i].type & P_REG))
 
522
                        {
 
523
                                // Just a temp. Should be replaced with more purposeful vars.
 
524
                                int value;
 
525
 
 
526
                                // modified by Hermes: test the register range
 
527
                                switch ((unsigned)opc->params[i].type)
 
528
                                { 
 
529
                                case P_REG18:
 
530
                                case P_REG19:
 
531
                                case P_REG1A:
 
532
                                        value = (opc->params[i].type >> 8) & 31;
 
533
                                        if ((int)par[i].val < value ||
 
534
                                                (int)par[i].val > value + get_mask_shifted_down(opc->params[i].mask))
 
535
                                        {
 
536
                                                if (ext) fprintf(stderr, "(ext) ");
 
537
                                                fprintf(stderr, "%s   (param %i)", cur_line.c_str(), current_param);
 
538
                                                ShowError(ERR_INVALID_REGISTER);
 
539
                                        }
 
540
                                        break;
 
541
                                case P_PRG:
 
542
                                        if ((int)par[i].val < 0 || (int)par[i].val > 0x3)
 
543
                                        {
 
544
                                                if (ext) fprintf(stderr, "(ext) ");
 
545
                                                fprintf(stderr, "%s   (param %i)", cur_line.c_str(), current_param);
 
546
                                                ShowError(ERR_INVALID_REGISTER);
 
547
                                        }
 
548
                                        break;
 
549
                                case P_ACC:
 
550
                                        if ((int)par[i].val < 0x20 || (int)par[i].val > 0x21)
 
551
                                        {
 
552
                                                if (ext) fprintf(stderr, "(ext) ");
 
553
                                                if (par[i].val >= 0x1e && par[i].val <= 0x1f) {
 
554
                                                        fprintf(stderr, "%i : %s ", code_line, cur_line.c_str());
 
555
                                                        fprintf(stderr, "WARNING: $ACM%d register used instead of $ACC%d register Line: %d Param: %d Ext: %d\n",
 
556
                                                                (par[i].val & 1), (par[i].val & 1), code_line, current_param, ext);
 
557
                                                }
 
558
                                                else if (par[i].val >= 0x1c && par[i].val <= 0x1d) {
 
559
                                                        fprintf(stderr, "WARNING: $ACL%d register used instead of $ACC%d register Line: %d Param: %d\n",
 
560
                                                                (par[i].val & 1), (par[i].val & 1), code_line, current_param);
 
561
                                                }
 
562
                                                else
 
563
                                                        ShowError(ERR_WRONG_PARAMETER_ACC);
 
564
                                        }
 
565
                                        break;
 
566
                                case P_ACCM:
 
567
                                        if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f)
 
568
                                        {
 
569
                                                if (ext) fprintf(stderr, "(ext) ");
 
570
                                                if (par[i].val >= 0x1c && par[i].val <= 0x1d)
 
571
                                                        fprintf(stderr, "WARNING: $ACL%d register used instead of $ACM%d register Line: %d Param: %d\n",
 
572
                                                                (par[i].val & 1), (par[i].val & 1), code_line, current_param);
 
573
                                                else if (par[i].val >= 0x20 && par[i].val <= 0x21)
 
574
                                                        fprintf(stderr, "WARNING: $ACC%d register used instead of $ACM%d register Line: %d Param: %d\n",
 
575
                                                                (par[i].val & 1), (par[i].val & 1), code_line, current_param);
 
576
                                                else
 
577
                                                        ShowError(ERR_WRONG_PARAMETER_ACC);
 
578
                                        }
 
579
                                        break;
 
580
 
 
581
                                case P_ACCL:
 
582
                                        if ((int)par[i].val < 0x1c || (int)par[i].val > 0x1d)
 
583
                                        {
 
584
                                                if (ext) fprintf(stderr, "(ext) ");
 
585
                                                if (par[i].val >= 0x1e && par[i].val <= 0x1f)
 
586
                                                {
 
587
                                                        fprintf(stderr, "%s ", cur_line.c_str());
 
588
                                                        fprintf(stderr, "WARNING: $ACM%d register used instead of $ACL%d register Line: %d Param: %d\n",
 
589
                                                                (par[i].val & 1), (par[i].val & 1), code_line, current_param);
 
590
                                                }
 
591
                                                else if (par[i].val >= 0x20 && par[i].val <= 0x21) {
 
592
                                                        fprintf(stderr, "%s ", cur_line.c_str());
 
593
                                                        fprintf(stderr, "WARNING: $ACC%d register used instead of $ACL%d register Line: %d Param: %d\n",
 
594
                                                                (par[i].val & 1), (par[i].val & 1), code_line, current_param);
 
595
                                                }
 
596
                                                else
 
597
                                                        ShowError(ERR_WRONG_PARAMETER_ACC);
 
598
                                        }
 
599
                                        break;
 
600
/*                              case P_ACCM_D: //P_ACC_MID:
 
601
                                        if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f)
 
602
                                        {
 
603
                                                ShowError(ERR_WRONG_PARAMETER_MID_ACC);
 
604
                                        }
 
605
                                        break;*/
 
606
                                }
 
607
                                continue;
 
608
                        }
 
609
 
 
610
                        switch (par[i].type & (P_REG | 7))
 
611
                        {
 
612
                        case P_REG:
 
613
                                if (ext) fprintf(stderr, "(ext) ");
 
614
                                ShowError(ERR_EXPECTED_PARAM_REG);
 
615
                                break;
 
616
                        case P_MEM:
 
617
                                if (ext) fprintf(stderr, "(ext) ");
 
618
                                ShowError(ERR_EXPECTED_PARAM_MEM);
 
619
                                break;
 
620
                        case P_VAL:
 
621
                                if (ext) fprintf(stderr, "(ext) ");
 
622
                                ShowError(ERR_EXPECTED_PARAM_VAL);
 
623
                                break;
 
624
                        case P_IMM:
 
625
                                if (ext) fprintf(stderr, "(ext) ");
 
626
                                ShowError(ERR_EXPECTED_PARAM_IMM);
 
627
                                break;
 
628
                        }
 
629
                        ShowError(ERR_WRONG_PARAMETER);
 
630
                        break;
 
631
                }
 
632
                else if ((opc->params[i].type & 3) != 0 && (par[i].type & 3) != 0)
 
633
                {
 
634
                        // modified by Hermes: test NUMBER range
 
635
                        int value = get_mask_shifted_down(opc->params[i].mask);
 
636
                        unsigned int valueu = 0xffff & ~(value >> 1);
 
637
                        if ((int)par[i].val < 0)
 
638
                        {
 
639
                                if (value == 7) // value 7 por sbclr/sbset
 
640
                                {
 
641
                                        fprintf(stderr,"Value must be from 0x0 to 0x%x\n", value);
 
642
                                        ShowError(ERR_OUT_RANGE_NUMBER);
 
643
                                }
 
644
                                else if (opc->params[i].type == P_MEM)
 
645
                                {
 
646
                                        if (value < 256)
 
647
                                                fprintf(stderr, "Address value must be from 0x%x to 0x%x\n",valueu, (value>>1));
 
648
                                        else
 
649
                                                fprintf(stderr, "Address value must be from 0x0 to 0x%x\n", value);
 
650
 
 
651
                                        ShowError(ERR_OUT_RANGE_NUMBER);
 
652
                                }
 
653
                                else if ((int)par[i].val < -((value >> 1) + 1))
 
654
                                {
 
655
                                        if (value < 128)
 
656
                                                fprintf(stderr, "Value must be from -0x%x to 0x%x, is %i\n",
 
657
                                                        (value >> 1) + 1, value >> 1, par[i].val);
 
658
                                        else
 
659
                                                fprintf(stderr, "Value must be from -0x%x to 0x%x or 0x0 to 0x%x, is %i\n",
 
660
                                                        (value >> 1) + 1, value >> 1, value, par[i].val);
 
661
 
 
662
                                        ShowError(ERR_OUT_RANGE_NUMBER);
 
663
                                }
 
664
                        }
 
665
                        else
 
666
                        {
 
667
                                if (value == 7) // value 7 por sbclr/sbset
 
668
                                {
 
669
                                        if (par[i].val > (unsigned)value)
 
670
                                        {
 
671
                                                fprintf(stderr,"Value must be from 0x%x to 0x%x, is %i\n",valueu, value, par[i].val);
 
672
                                                ShowError(ERR_OUT_RANGE_NUMBER);
 
673
                                        }
 
674
                                }
 
675
                                else if (opc->params[i].type == P_MEM)
 
676
                                {
 
677
                                        if (value < 256)
 
678
                                                value >>= 1; // addressing 8 bit with sign
 
679
                                        if (par[i].val > (unsigned)value &&
 
680
                                                (par[i].val < valueu || par[i].val > (unsigned)0xffff))
 
681
                                        {
 
682
                                                if (value < 256)
 
683
                                                        fprintf(stderr,"Address value must be from 0x%x to 0x%x, is %04x\n", valueu, value, par[i].val);
 
684
                                                else
 
685
                                                        fprintf(stderr,"Address value must be minor of 0x%x\n", value+1);
 
686
                                                ShowError(ERR_OUT_RANGE_NUMBER);
 
687
                                        }
 
688
                                }
 
689
                                else
 
690
                                {
 
691
                                        if (value < 128)
 
692
                                                value >>= 1; // special case ASL/ASR/LSL/LSR
 
693
                                        if (par[i].val > (unsigned)value)
 
694
                                        {
 
695
                                                if (value < 64)
 
696
                                                        fprintf(stderr,"Value must be from -0x%x to 0x%x, is %i\n", (value + 1), value, par[i].val);
 
697
                                                else
 
698
                                                        fprintf(stderr,"Value must be minor of 0x%x, is %i\n", value + 1, par[i].val);
 
699
                                                ShowError(ERR_OUT_RANGE_NUMBER);
 
700
                                        }
 
701
                                }
 
702
                        }
 
703
                        continue;
 
704
                }
 
705
        }
 
706
        m_current_param = 0;
 
707
        return true;
 
708
}
 
709
 
 
710
 
 
711
// Merge opcode with params.
 
712
void DSPAssembler::BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf)
 
713
{
 
714
        outbuf[m_cur_addr] |= opc->opcode;
 
715
        for (u32 i = 0; i < par_count; i++)
 
716
        {
 
717
                // Ignore the "reverse" parameters since they are implicit.
 
718
                if (opc->params[i].type != P_ACC_D && opc->params[i].type != P_ACCM_D)
 
719
                {
 
720
                        u16 t16 = outbuf[m_cur_addr + opc->params[i].loc];
 
721
                        u16 v16 = par[i].val;
 
722
                        if (opc->params[i].lshift > 0)
 
723
                                v16 <<= opc->params[i].lshift;
 
724
                        else
 
725
                                v16 >>= -opc->params[i].lshift;
 
726
                        v16 &= opc->params[i].mask;
 
727
                        outbuf[m_cur_addr + opc->params[i].loc] = t16 | v16;
 
728
                }
 
729
        }
 
730
}
 
731
 
 
732
void DSPAssembler::InitPass(int pass)
 
733
{
 
734
        failed = false;
 
735
        if (pass == 1)
 
736
        {
 
737
                // Reset label table. Pre-populate with hw addresses and registers.
 
738
                labels.Clear();
 
739
                labels.RegisterDefaults();
 
740
                aliases.clear();
 
741
                aliases["S15"] = "SET15";
 
742
                aliases["S16"] = "SET16";
 
743
                aliases["S40"] = "SET40";
 
744
        }
 
745
        m_cur_addr = 0;
 
746
        m_totalSize = 0;
 
747
        cur_segment = SEGMENT_CODE;
 
748
        segment_addr[SEGMENT_CODE] = 0;
 
749
        segment_addr[SEGMENT_DATA] = 0;
 
750
        segment_addr[SEGMENT_OVERLAY] = 0;
 
751
}
 
752
 
 
753
bool DSPAssembler::AssembleFile(const char *fname, int pass)
 
754
{
 
755
        int disable_text = 0; // modified by Hermes
 
756
 
 
757
        std::ifstream fsrc;
 
758
        OpenFStream(fsrc, fname, std::ios_base::in);
 
759
 
 
760
        if (fsrc.fail())
 
761
        {
 
762
                std::cerr << "Cannot open file " << fname << std::endl;
 
763
                return false;
 
764
        }
 
765
 
 
766
        //printf("%s: Pass %d\n", fname, pass);
 
767
        code_line = 0;
 
768
        m_cur_pass = pass;
 
769
 
 
770
#define LINEBUF_SIZE 1024
 
771
        char line[LINEBUF_SIZE] = {0};
 
772
        while (!failed && !fsrc.fail() && !fsrc.eof())
 
773
        {
 
774
                int opcode_size = 0;
 
775
                fsrc.getline(line, LINEBUF_SIZE);
 
776
                if(fsrc.fail())
 
777
                        break;
 
778
                
 
779
                cur_line = line;
 
780
                //printf("A: %s\n", line);
 
781
                code_line++;
 
782
 
 
783
                param_t params[10] = {{0, P_NONE, NULL}};
 
784
                param_t params_ext[10] = {{0, P_NONE, NULL}};
 
785
                
 
786
                bool upper = true;
 
787
                for (int i = 0; i < LINEBUF_SIZE; i++)
 
788
                {
 
789
                        char c = line[i];
 
790
                        // This stuff handles /**/ and // comments.
 
791
                        // modified by Hermes : added // and /* */ for long commentaries 
 
792
                        if (c == '/')
 
793
                        {
 
794
                                if (i < 1023)
 
795
                                {
 
796
                                        if (line[i+1] == '/')
 
797
                                                c = 0x00;
 
798
                                        else if (line[i+1] == '*') 
 
799
                                        {
 
800
                                                // toggle comment mode.
 
801
                                                disable_text = !disable_text;
 
802
                                        }
 
803
                                }
 
804
                        }
 
805
                        else if (c == '*')
 
806
                        {
 
807
                                if (i < 1023 && line[i+1] == '/' && disable_text)
 
808
                                {
 
809
                                        disable_text = 0;
 
810
                                        c = 32;
 
811
                                        line[i + 1] = 32;
 
812
                                }
 
813
                        }
 
814
 
 
815
                        // turn text into spaces if disable_text is on (in a comment).
 
816
                        if (disable_text && ((unsigned char)c) > 32) c = 32;
 
817
 
 
818
                        if (c == 0x0a || c == 0x0d || c == ';')
 
819
                                c = 0x00;
 
820
                        if (c == 0x09)                          // tabs to spaces
 
821
                                c = ' ';
 
822
                        if (c == '"')
 
823
                                upper = !upper;
 
824
                        if (upper && c >= 'a' && c <= 'z')      // convert to uppercase
 
825
                                c = c - 'a' + 'A';
 
826
                        line[i] = c;
 
827
                        if (c == 0)
 
828
                                break; // modified by Hermes
 
829
                }
 
830
                char *ptr = line;
 
831
 
 
832
                std::string label;
 
833
 
 
834
                size_t col_pos = std::string(line).find(":");
 
835
                if (col_pos != std::string::npos)
 
836
                {
 
837
                        bool valid = true;
 
838
 
 
839
                        for(int j = 0; j < (int)col_pos; j++)
 
840
                        {
 
841
                                if (j == 0)
 
842
                                        if (!((ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_')))
 
843
                                                valid = false;
 
844
                                if (!((ptr[j] >= '0' && ptr[j] <= '9') || (ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_')))
 
845
                                        valid = false;
 
846
                        }
 
847
                        if (valid)
 
848
                        {
 
849
                                label = std::string(line).substr(0, col_pos);
 
850
                                ptr     += col_pos + 1;
 
851
                        }
 
852
                }
 
853
 
 
854
                char *opcode = NULL;
 
855
                opcode = strtok(ptr, " ");
 
856
                char *opcode_ext = NULL;
 
857
 
 
858
                u32 params_count = 0;
 
859
                u32 params_count_ext = 0;
 
860
                if (opcode)
 
861
                {
 
862
                        if ((opcode_ext = strstr(opcode, "'")) != NULL)
 
863
                        {
 
864
                                opcode_ext[0] = '\0';
 
865
                                opcode_ext++;
 
866
                                if (strlen(opcode_ext) == 0)
 
867
                                        opcode_ext = NULL;
 
868
                        }
 
869
                        // now we have opcode and label
 
870
 
 
871
                        params_count = 0;
 
872
                        params_count_ext = 0;
 
873
 
 
874
                        char *paramstr = strtok(NULL, "\0");
 
875
                        char *paramstr_ext = 0;
 
876
                        // there is valid opcode so probably we have parameters
 
877
 
 
878
                        if (paramstr)
 
879
                        {
 
880
                                if ((paramstr_ext = strstr(paramstr, ":")) != NULL)
 
881
                                {
 
882
                                        paramstr_ext[0] = '\0';
 
883
                                        paramstr_ext++;
 
884
                                }
 
885
                        }
 
886
 
 
887
                        if (paramstr)
 
888
                                params_count = GetParams(paramstr, params);
 
889
                        if (paramstr_ext)
 
890
                                params_count_ext = GetParams(paramstr_ext, params_ext);
 
891
                }
 
892
 
 
893
                if (!label.empty())
 
894
                {
 
895
                        // there is a valid label so lets store it in labels table
 
896
                        u32 lval = m_cur_addr;
 
897
                        if (opcode)
 
898
                        {
 
899
                                if (strcmp(opcode, "EQU") == 0)
 
900
                                {
 
901
                                        lval = params[0].val;
 
902
                                        opcode = NULL;
 
903
                                }
 
904
                        }
 
905
                        if (pass == 1)
 
906
                                labels.RegisterLabel(label, lval);
 
907
                }
 
908
 
 
909
                if (opcode == NULL)
 
910
                        continue;
 
911
 
 
912
                // check if opcode is reserved compiler word
 
913
                if (strcmp("INCLUDE", opcode) == 0)
 
914
                {
 
915
                        if (params[0].type == P_STR)
 
916
                        {
 
917
                                char *tmpstr;
 
918
                                u32 thisCodeline = code_line;
 
919
                                
 
920
                                if (include_dir.size())
 
921
                                {
 
922
                                        tmpstr = (char *)malloc(include_dir.size() + strlen(params[0].str) + 2);
 
923
                                        sprintf(tmpstr, "%s/%s", include_dir.c_str(), params[0].str);
 
924
                                }
 
925
                                else
 
926
                                {
 
927
                                        tmpstr = (char *)malloc(strlen(params[0].str) + 1);
 
928
                                        strcpy(tmpstr, params[0].str);
 
929
                                }
 
930
                                
 
931
                                AssembleFile(tmpstr, pass);
 
932
 
 
933
                                code_line = thisCodeline;
 
934
 
 
935
                                free(tmpstr);
 
936
                        }
 
937
                        else
 
938
                                ShowError(ERR_EXPECTED_PARAM_STR);
 
939
                        continue;
 
940
                }
 
941
 
 
942
                if (strcmp("INCDIR", opcode) == 0)
 
943
                {
 
944
                        if (params[0].type == P_STR)
 
945
                                include_dir = params[0].str;
 
946
                        else
 
947
                                ShowError(ERR_EXPECTED_PARAM_STR);
 
948
                        continue;
 
949
                }
 
950
 
 
951
                if (strcmp("ORG", opcode) == 0)
 
952
                {
 
953
                        if (params[0].type == P_VAL)
 
954
                                m_cur_addr = params[0].val;
 
955
                        else
 
956
                                ShowError(ERR_EXPECTED_PARAM_VAL);
 
957
                        continue;
 
958
                }
 
959
 
 
960
                if (strcmp("SEGMENT", opcode) == 0)
 
961
                {
 
962
                        if (params[0].type == P_STR)
 
963
                        {
 
964
                                segment_addr[cur_segment] = m_cur_addr;
 
965
                                if (strcmp("DATA", params[0].str) == 0)
 
966
                                        cur_segment = SEGMENT_DATA;
 
967
                                if (strcmp("CODE", params[0].str) == 0)
 
968
                                        cur_segment = SEGMENT_CODE;
 
969
                                m_cur_addr = segment_addr[cur_segment];
 
970
                        }
 
971
                        else
 
972
                                ShowError(ERR_EXPECTED_PARAM_STR);
 
973
                        continue;
 
974
                }
 
975
 
 
976
                const opc_t *opc = FindOpcode(opcode, params_count, opcodes, opcodes_size);
 
977
                if (!opc)
 
978
                        opc = &cw;
 
979
 
 
980
                opcode_size = opc->size;
 
981
 
 
982
                VerifyParams(opc, params, params_count);
 
983
 
 
984
                const opc_t *opc_ext = NULL;
 
985
                // Check for opcode extensions.
 
986
                if (opc->extended)
 
987
                {
 
988
                        if (opcode_ext)
 
989
                        {
 
990
                                opc_ext = FindOpcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size);
 
991
                                VerifyParams(opc_ext, params_ext, params_count_ext, true);
 
992
                        }
 
993
                        else if (params_count_ext)
 
994
                                ShowError(ERR_EXT_PAR_NOT_EXT);
 
995
                }
 
996
                else
 
997
                {
 
998
                        if (opcode_ext)
 
999
                                ShowError(ERR_EXT_CANT_EXTEND_OPCODE);
 
1000
                        if (params_count_ext)
 
1001
                                ShowError(ERR_EXT_PAR_NOT_EXT);
 
1002
                }
 
1003
 
 
1004
                if (pass == 2)
 
1005
                {
 
1006
                        // generate binary
 
1007
                        ((u16 *)gdg_buffer)[m_cur_addr] = 0x0000;
 
1008
                        BuildCode(opc, params, params_count, (u16 *)gdg_buffer);
 
1009
                        if (opc_ext)
 
1010
                                BuildCode(opc_ext, params_ext, params_count_ext, (u16 *)gdg_buffer);
 
1011
                }
 
1012
 
 
1013
                m_cur_addr += opcode_size;
 
1014
                m_totalSize += opcode_size;
 
1015
        };
 
1016
 
 
1017
        if (!failed)
 
1018
                fsrc.close();
 
1019
 
 
1020
        return !failed;
 
1021
}