]> Shamusworld >> Repos - rmac/blob - risca.c
7786beb2de447fd6a00420e9e8e704834e680721
[rmac] / risca.c
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // RISCA.C - GPU/DSP Assembler
4 // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source Utilised with the Kind Permission of Landon Dyer
7 //
8
9 #include "risca.h"
10 #include "error.h"
11 #include "sect.h"
12 #include "token.h"
13 #include "expr.h"
14 #include "direct.h"
15 #include "mark.h"
16 #include "amode.h"
17
18 #define DEF_MR                                                  // Declar keyword values
19 #include "risckw.h"                                             // Incl generated risc keywords
20
21 #define DEF_KW                                                  // Declare keyword values 
22 #include "kwtab.h"                                              // Incl generated keyword tables & defs
23
24 unsigned altbankok = 0;                                 // Ok to use alternate register bank
25 unsigned orgactive = 0;                                 // RISC org directive active
26 unsigned orgaddr = 0;                                   // Org'd address
27 unsigned orgwarning = 0;                                // Has an ORG warning been issued
28 //unsigned previousop = 0;                              // Used for NOP padding checks
29 //unsigned currentop = 0;                                       // Used for NOP padding checks
30
31 char reg_err[] = "missing register R0...R31";
32
33 // Jaguar Jump Condition Names
34 char condname[MAXINTERNCC][5] = { 
35         "NZ", "Z", "NC", "NCNZ", "NCZ", "C", "CNZ", "CZ", "NN", "NNNZ", "NNZ",
36         "N", "N_NZ", "N_Z ", "T", "A", "NE", "EQ", "CC", "HS", "HI", "CS", "LO",
37         "PL", "MI", "F"
38 };
39
40 // Jaguar Jump Condition Numbers
41 char condnumber[] = { 1, 2, 4, 5, 6, 8, 9, 10, 20, 21, 22, 24, 25, 26,
42                       0, 0, 1, 2, 4, 4, 5,  8,  8, 20, 24, 31};
43
44 struct opcoderecord roptbl[] = {
45         { MR_ADD,     RI_TWO,    0 },
46         { MR_ADDC,    RI_TWO,    1 },
47         { MR_ADDQ,    RI_NUM_32, 2 },
48         { MR_ADDQT,   RI_NUM_32, 3 },
49         { MR_SUB,     RI_TWO,    4 },
50         { MR_SUBC,    RI_TWO,    5 },
51         { MR_SUBQ,    RI_NUM_32, 6 },
52         { MR_SUBQT,   RI_NUM_32, 7 },
53         { MR_NEG,     RI_ONE,    8 },
54         { MR_AND,     RI_TWO,    9 },
55         { MR_OR,      RI_TWO,    10 },
56         { MR_XOR,     RI_TWO,    11 },
57         { MR_NOT,     RI_ONE,    12 },
58         { MR_BTST,    RI_NUM_31, 13 },
59         { MR_BSET,    RI_NUM_31, 14 },
60         { MR_BCLR,    RI_NUM_31, 15 },
61         { MR_MULT,    RI_TWO,    16 },
62         { MR_IMULT,   RI_TWO,    17 },
63         { MR_IMULTN,  RI_TWO,    18 },
64         { MR_RESMAC,  RI_ONE,    19 },
65         { MR_IMACN,   RI_TWO,    20 },
66         { MR_DIV,     RI_TWO,    21 },
67         { MR_ABS,     RI_ONE,    22 },
68         { MR_SH,      RI_TWO,    23 },
69         { MR_SHLQ,    RI_NUM_32, 24 + SUB32 },
70         { MR_SHRQ,    RI_NUM_32, 25 },
71         { MR_SHA,     RI_TWO,    26 },
72         { MR_SHARQ,   RI_NUM_32, 27 },
73         { MR_ROR,     RI_TWO,    28 },
74         { MR_RORQ,    RI_NUM_32, 29 },
75         { MR_ROLQ,    RI_NUM_32, 29 + SUB32 },
76         { MR_CMP,     RI_TWO,    30 },
77         { MR_CMPQ,    RI_NUM_15, 31 },
78         { MR_SAT8,    RI_ONE,    32 + GPUONLY },
79         { MR_SUBQMOD, RI_NUM_32, 32 + DSPONLY },
80         { MR_SAT16,   RI_ONE,    33 + GPUONLY },
81         { MR_SAT16S,  RI_ONE,    33 + DSPONLY },
82         { MR_MOVEQ,   RI_NUM_31, 35 },
83         { MR_MOVETA,  RI_TWO,    36 },
84         { MR_MOVEFA,  RI_TWO,    37 },
85         { MR_MOVEI,   RI_MOVEI,  38 },
86         { MR_LOADB,   RI_LOADN,  39 },
87         { MR_LOADW,   RI_LOADN,  40 },
88         { MR_LOADP,   RI_LOADN,  42 + GPUONLY },
89         { MR_SAT32S,  RI_ONE,    42 + DSPONLY },
90         { MR_STOREB,  RI_STOREN, 45 },
91         { MR_STOREW,  RI_STOREN, 46 },
92         { MR_STOREP,  RI_STOREN, 48 + GPUONLY },
93         { MR_MIRROR,  RI_ONE,    48 + DSPONLY },
94         { MR_JUMP,    RI_JUMP,   52 },
95         { MR_JR,      RI_JR,     53 },
96         { MR_MMULT,   RI_TWO,    54 },
97         { MR_MTOI,    RI_TWO,    55 },
98         { MR_NORMI,   RI_TWO,    56 },
99         { MR_NOP,     RI_NONE,   57 },
100         { MR_SAT24,   RI_ONE,    62 },
101         { MR_UNPACK,  RI_ONE,    63 + GPUONLY },
102         { MR_PACK,    RI_ONE,    63 + GPUONLY },
103         { MR_ADDQMOD, RI_NUM_32, 63 + DSPONLY },
104         { MR_MOVE,    RI_MOVE,   0 },
105         { MR_LOAD,    RI_LOAD,   0 },
106         { MR_STORE,   RI_STORE,  0 }
107 };
108
109
110 //
111 // Convert a String to Uppercase
112 //
113 void strtoupper(char * s)
114 {
115         while (*s)
116         {
117                 *s = (char)(toupper(*s));
118                 s++;
119         }
120 }
121
122
123 //
124 // Build RISC Instruction Word
125 //
126 void risc_instruction_word(unsigned short parm, int reg1, int reg2)
127 {
128 //      int value = 0xE400;
129
130         // Opcode tracking for nop padding
131 //      previousop = currentop;
132 //      currentop = parm;
133
134         if (!orgwarning && !orgactive)
135         {
136                 // Check for absolute address setting
137 //              if (!orgactive && !in_main)
138 //              {
139                         warn("GPU/DSP code outside of absolute section");
140                         orgwarning = 1;
141 //              }
142         }
143
144 #if 0
145         if (jpad)
146         {                                               // JPAD directive
147                 //                JUMP                   JR                    NOP
148                 if (((previousop == 52) || (previousop == 53)) && (currentop != 57))
149                         D_word(value);                                     // Insert NOP
150         }
151         else
152 //      {
153                 //               JUMP                   JR
154                 if ((previousop == 52) || (previousop == 53))
155                 {
156                         switch (currentop)
157                         {
158                         case 38:
159                                 warn("NOP inserted before MOVEI instruction.");
160                                 D_word(value);
161                                 break;
162                         case 53:
163                                 warn("NOP inserted before JR instruction.");
164                                 D_word(value);
165                                 break;
166                         case 52:
167                                 warn("NOP inserted before JUMP instruction.");
168                                 D_word(value);
169                                 break;
170                         case 51:
171                                 warn("NOP inserted before MOVE PC instruction.");
172                                 D_word(value);
173                                 break;
174                         default:
175                                 break;
176                         }
177                 }
178 //      }
179
180         if (currentop == 20)
181         {                                    // IMACN checks
182                 if ((previousop != 18) && (previousop != 20))
183                         error("IMULTN/IMACN instruction must preceed IMACN instruction");
184         }
185
186         if (currentop == 19)
187         {                                    // RESMAC checks
188                 if (previousop != 20)
189                         error("IMACN instruction must preceed RESMAC instruction");
190         }
191 #endif
192
193         int value = ((parm & 0x3F) << 10) + ((reg1 & 0x1F) << 5) + (reg2 & 0x1F);
194         D_word(value);
195 }
196
197
198 //
199 // Get a RISC Register
200 //
201 int getregister(WORD rattr)
202 {
203         VALUE eval;                                     // Expression value
204         WORD eattr;                                     // Expression attributes
205         SYM * esym;                                     // External symbol involved in expr.
206         TOKEN r_expr[EXPRSIZE];         // Expression token list
207
208         // Evaluate what's in the global "tok" buffer
209         if (expr(r_expr, &eval, &eattr, &esym) != OK)
210         {
211                 error("Malformed opcode");
212                 return ERROR;
213         }
214
215         if ((challoc - ch_size) < 4)
216                 chcheck(4L);
217
218         if (!(eattr & DEFINED))
219         {
220                 fixup((WORD)(FU_WORD | rattr), sloc, r_expr);      
221                 return 0;
222         }
223
224         // If we got a register in range (0-31), return it
225         if ((eval >= 0) && (eval <= 31))
226                 return eval;
227
228         // Otherwise, it's out of range & we flag an error
229         error(reg_err);
230         return ERROR;
231 }
232
233
234 //
235 // Do RISC Code Generation
236 //
237 int risccg(int state)
238 {
239 //      unsigned short parm;            // Opcode parameters
240 //      unsigned type;                          // Opcode type
241         int reg1;                                       // Register 1
242         int reg2;                                       // Register 2
243         int val = 0;                            // Constructed value
244         char scratch[80];
245         SYM * ccsym;
246         SYM * sy;
247         int i;                                          // Iterator
248         int t, c;
249         WORD tdb;
250         unsigned locptr = 0;            // Address location pointer
251         unsigned page_jump = 0;         // Memory page jump flag
252         VALUE eval;                                     // Expression value
253         WORD eattr;                                     // Expression attributes
254         SYM * esym;                                     // External symbol involved in expr.
255         TOKEN r_expr[EXPRSIZE];         // Expression token list
256         WORD defined;                           // Symbol defined flag
257         WORD attrflg;
258         int indexed;                            // Indexed register flag
259
260         // Get opcode parameter and type
261         unsigned short parm = (WORD)(roptbl[state - 3000].parm);
262         unsigned type = roptbl[state - 3000].typ;
263
264         // Detect whether the opcode parmeter passed determines that the opcode is
265         // specific to only one of the RISC processors and ensure it is legal in
266         // the current code section. If not then error and return.
267         if (((parm & GPUONLY) && rdsp) || ((parm & DSPONLY) && rgpu))
268         {
269                 error("Opcode is not valid in this code section");
270                 return ERROR;
271         }
272
273         // Process RISC opcode
274         switch (type)
275         {
276         // No operand instructions
277         // NOP
278         case RI_NONE: 
279                 risc_instruction_word(parm, 0, 0);
280                 break;
281
282         // Single operand instructions (Rd)
283         // ABS, MIRROR, NEG, NOT, PACK, RESMAC, SAT8, SAT16, SAT16S, SAT24, SAT32S, UNPACK
284         case RI_ONE:
285                 reg2 = getregister(FU_REGTWO);
286                 at_eol();
287                 risc_instruction_word(parm, parm >> 6, reg2);
288                 break;   
289
290         // Two operand instructions (Rs,Rd)
291         // ADD, ADDC, AND, CMP, DIV, IMACN, IMULT, IMULTN, MOVEFA, MOVETA, MULT, MMULT, 
292         // MTOI, NORMI, OR, ROR, SH, SHA, SUB, SUBC, XOR
293         case RI_TWO:                      
294                 if (parm == 37)
295                         altbankok = 1;                      // MOVEFA
296
297                 reg1 = getregister(FU_REGONE);
298                 CHECK_COMMA;         
299
300                 if (parm == 36)
301                         altbankok = 1;                      // MOVETA
302
303                 reg2 = getregister(FU_REGTWO);
304                 at_eol();
305                 risc_instruction_word(parm, reg1, reg2);
306                 break;
307
308         // Numeric operand (n,Rd) where n = -16..+15
309         // CMPQ
310         case RI_NUM_15:                   
311
312         // Numeric operand (n,Rd) where n = 0..31
313         // BCLR, BSET, BTST, MOVEQ
314         case RI_NUM_31:      
315
316         // Numeric operand (n,Rd) where n = 1..32
317         // ADDQ, ADDQMOD, ADDQT, SHARQ, SHLQ, SHRQ, SUBQ, SUBQMOD, SUBQT, ROLQ, RORQ
318         case RI_NUM_32:                   
319                 switch (type)
320                 {
321                 case RI_NUM_15:
322                         reg1 = -16; reg2 = 15; attrflg = FU_NUM15;
323                         break;
324                 default:
325                 case RI_NUM_31:
326                         reg1 =   0; reg2 = 31; attrflg = FU_NUM31;
327                         break;
328                 case RI_NUM_32:
329                         reg1 =   1; reg2 = 32; attrflg = FU_NUM32;
330                         break;
331                 }
332
333                 if (parm & SUB32) attrflg |= FU_SUB32;
334                 {
335                         if (*tok == '#')
336                         {
337                                 tok++;
338
339                                 if (expr(r_expr, &eval, &eattr, &esym) != OK)
340                                         goto malformed;
341                                 else
342                                 {
343                                         defined = (WORD)(eattr & DEFINED);
344
345                                         if ((challoc - ch_size) < 4)
346                                                 chcheck(4L);
347
348                                         if (!defined)
349                                         {
350                                                 fixup((WORD)(FU_WORD | attrflg), sloc, r_expr);
351                                                 reg1 = 0;
352                                         }
353                                         else
354                                         {
355                                                 if ((int)eval < reg1 || (int)eval > reg2)
356                                                 {
357                                                         error("constant out of range");
358                                                         return ERROR;
359                                                 }
360
361                                                 if (parm & SUB32) 
362                                                         reg1 = 32 - eval; 
363                                                 else if (type == RI_NUM_32)
364                                                         reg1 = (reg1 == 32 ? 0 : eval);
365                                                 else
366                                                         reg1 = eval;
367                                         }
368                                 }
369                         }
370                         else
371                                 goto malformed;
372                 }
373
374                 CHECK_COMMA;
375                 reg2 = getregister(FU_REGTWO);
376                 at_eol();
377                 risc_instruction_word(parm, reg1, reg2);
378                 break;
379
380         // Move Immediate--n,Rn--n in Second Word
381         case RI_MOVEI:
382                 if (*tok != '#')
383                         goto malformed;
384
385 //              {
386                         tok++;
387
388                         if (expr(r_expr, &eval, &eattr, &esym) != OK)
389                         {
390                                 malformed:
391                                 error("malformed opcode");
392                                 return ERROR;
393                         }
394                         else
395                         {
396                                 // Opcode tracking for nop padding
397 //                              previousop = currentop;                          
398 //                              currentop = parm;
399
400 #if 0
401                                 // JUMP or JR
402                                 if ((previousop == 52) || (previousop == 53) && !jpad)
403                                 {
404                                         warn("NOP inserted before MOVEI instruction.");   
405                                         D_word(0xE400);
406                                 }
407 #endif
408
409                                 tdb = (WORD)(eattr & TDB);
410                                 defined = (WORD)(eattr & DEFINED);
411
412                                 if ((challoc - ch_size) < 4)
413                                         chcheck(4L);
414
415                                 if (!defined)
416                                 {
417                                         fixup(FU_LONG | FU_MOVEI, sloc + 2, r_expr);
418                                         eval = 0;
419                                 }
420                                 else
421                                 {
422                                         if (tdb)
423                                                 rmark(cursect, sloc + 2, tdb, MLONG | MMOVEI, NULL);
424                                 }       
425
426                                 val = eval;
427
428 #if 0
429                                 // Store the defined flags and value of the movei when used in mjump
430                                 if (mjump_align)
431                                 {
432                                         mjump_defined = defined;
433                                         mjump_dest = val;
434                                 }
435 #endif
436                         }
437 //              }
438 //              else
439 //                      goto malformed;
440
441                 tok++;
442                 reg2 = getregister(FU_REGTWO);
443                 at_eol();
444                 D_word((((parm & 0x3F) << 10) + reg2));
445                 val = ((val >> 16) & 0x0000FFFF) | ((val << 16) & 0xFFFF0000);
446                 D_long(val);
447                 break;
448
449         case RI_MOVE:                     // PC,Rd or Rs,Rd
450                 if (*tok == KW_PC)
451                 {
452                         parm = 51;
453                         reg1 = 0;
454                         ++tok;
455                 }
456                 else
457                 {
458                         parm = 34;
459                         reg1 = getregister(FU_REGONE);
460                 }
461
462                 CHECK_COMMA;
463                 reg2 = getregister(FU_REGTWO);
464                 at_eol();
465                 risc_instruction_word(parm, reg1, reg2);
466                 break;
467
468         // (Rn),Rn = 41 / (R14/R15+n),Rn = 43/44 / (R14/R15+Rn),Rn = 58/59
469         case RI_LOAD:          
470                 indexed = 0;
471                 parm = 41;
472
473                 if (*tok != '(')
474                         goto malformed;
475
476                 tok++;
477
478                 if ((*tok == KW_R14 || *tok == KW_R15) && (*(tok+1) != ')')) 
479                         indexed = (*tok - KW_R0);
480
481                 if (*tok == SYMBOL)
482                 {
483 //                      sy = lookup((char *)tok[1], LABEL, 0);
484                         sy = lookup(string[tok[1]], LABEL, 0);
485
486                         if (!sy)
487                         {
488                                 error(reg_err);
489                                 return ERROR;
490                         }
491
492                         if (sy->sattre & EQUATEDREG)
493                         {
494                                 if (((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15)
495                                         && (*(tok+2) != ')'))
496                                 {
497                                         indexed = (sy->svalue & 0x1F);
498                                         ++tok;
499                                 }
500                         }
501                 }
502
503                 if (!indexed)
504                 {
505                         reg1 = getregister(FU_REGONE);
506                 }
507                 else
508                 {
509                         reg1 = indexed;
510                         indexed = 0;
511                         ++tok;
512
513                         if (*tok == '+')
514                         {
515                                 parm = (WORD)(reg1 - 14 + 58);
516                                 tok++;
517
518                                 if (*tok >= KW_R0 && *tok <= KW_R31)
519                                 {
520                                         indexed = 1;
521                                 }
522
523                                 if (*tok == SYMBOL)
524                                 {
525 //                                      sy = lookup((char *)tok[1], LABEL, 0);
526                                         sy = lookup(string[tok[1]], LABEL, 0);
527
528                                         if (!sy)
529                                         {
530                                                 error(reg_err);
531                                                 return ERROR;
532                                         }
533
534                                         if (sy->sattre & EQUATEDREG)
535                                         {
536                                                 indexed = 1;
537                                         } 
538                                 }
539
540                                 if (indexed)
541                                 {
542                                         reg1 = getregister(FU_REGONE);
543                                 }
544                                 else
545                                 {
546                                         if (expr(r_expr, &eval, &eattr, &esym) != OK)
547                                         {
548                                                 goto malformed;
549                                         }
550                                         else
551                                         {
552                                                 tdb = (WORD)(eattr & TDB);
553                                                 defined = (WORD)(eattr & DEFINED);
554
555                                                 if ((challoc - ch_size) < 4)
556                                                         chcheck(4L);
557
558                                                 if (!defined)
559                                                 {
560                                                         error("constant expected");
561                                                         return ERROR;
562                                                         //fixup(FU_WORD|FU_REGONE, sloc, r_expr);
563                                                         reg1 = 0;
564                                                 }
565                                                 else
566                                                 {
567                                                         reg1 = eval;
568
569                                                         if (reg1 == 0)
570                                                         {
571                                                                 reg1 = 14 + (parm - 58);
572                                                                 parm = 41;
573                                                                 warn("NULL offset removed");
574                                                         }
575                                                         else
576                                                         {
577                                                                 if (reg1 < 1 || reg1 > 32)
578                                                                 {
579                                                                         error("constant out of range");
580                                                                         return ERROR;
581                                                                 }
582
583                                                                 if (reg1 == 32)
584                                                                         reg1 = 0;
585
586                                                                 parm = (WORD)(parm - 58 + 43);
587                                                         }
588                                                 }
589                                         }
590                                 }
591                         }
592                         else
593                         {
594                                 reg1 = getregister(FU_REGONE);
595                         }
596                 }
597
598                 if (*tok != ')')
599                         goto malformed;
600
601                 tok++;
602                 CHECK_COMMA;
603                 reg2 = getregister(FU_REGTWO);
604                 at_eol();
605                 risc_instruction_word(parm, reg1, reg2);
606                 break;
607
608         // Rn,(Rn) = 47 / Rn,(R14/R15+n) = 49/50 / Rn,(R14/R15+Rn) = 60/61
609         case RI_STORE:    
610                 parm = 47;
611                 reg1 = getregister(FU_REGONE);
612                 CHECK_COMMA;
613
614                 if (*tok != '(') goto malformed;
615
616                 tok++;
617                 indexed = 0;
618
619                 if ((*tok == KW_R14 || *tok == KW_R15) && (*(tok + 1) != ')')) 
620                         indexed = (*tok - KW_R0);
621
622                 if (*tok == SYMBOL)
623                 {
624 //                      sy = lookup((char *)tok[1], LABEL, 0);
625                         sy = lookup(string[tok[1]], LABEL, 0);
626
627                         if (!sy)
628                         {
629                                 error(reg_err);
630                                 return ERROR;
631                         }
632
633                         if (sy->sattre & EQUATEDREG) 
634                         {
635                                 if (((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15)
636                                         && (*(tok + 2) != ')'))
637                                 {
638                                         indexed = (sy->svalue & 0x1F);
639                                         tok++;
640                                 }
641                         }
642                 }
643
644                 if (!indexed)
645                 {
646                         reg2 = getregister(FU_REGTWO);
647                 }
648                 else
649                 {
650                         reg2 = indexed;
651                         indexed = 0;
652                         tok++;
653
654                         if (*tok == '+')
655                         {
656                                 parm = (WORD)(reg2 - 14 + 60);
657                                 tok++;
658
659                                 if (*tok >= KW_R0 && *tok <= KW_R31)
660                                 {
661                                         indexed = 1;
662                                 }
663
664                                 if (*tok == SYMBOL)
665                                 {
666 //                                      sy = lookup((char *)tok[1], LABEL, 0);
667                                         sy = lookup(string[tok[1]], LABEL, 0);
668
669                                         if (!sy)
670                                         {
671                                                 error(reg_err);
672                                                 return ERROR;
673                                         }
674
675                                         if (sy->sattre & EQUATEDREG)
676                                         {
677                                                 indexed = 1;
678                                         }
679                                 }
680
681                                 if (indexed)
682                                 {
683                                         reg2 = getregister(FU_REGTWO);
684                                 }
685                                 else
686                                 {
687                                         if (expr(r_expr, &eval, &eattr, &esym) != OK)
688                                         {
689                                                 goto malformed;
690                                         }
691                                         else
692                                         {
693                                                 tdb = (WORD)(eattr & TDB);
694                                                 defined = (WORD)(eattr & DEFINED);
695
696                                                 if ((challoc - ch_size) < 4)
697                                                         chcheck(4L);
698
699                                                 if (!defined)
700                                                 {
701                                                         fixup(FU_WORD | FU_REGTWO, sloc, r_expr);
702                                                         reg2 = 0;
703                                                 }
704                                                 else
705                                                 {
706                                                         reg2 = eval;
707
708                                                         if (reg2 == 0 )
709                                                         {
710                                                                 reg2 = 14 + (parm - 60);
711                                                                 parm = 47;
712                                                                 warn("NULL offset removed");
713                                                         }
714                                                         else
715                                                         {
716                                                                 if (reg2 < 1 || reg2 > 32)
717                                                                 {
718                                                                         error("constant out of range");
719                                                                         return ERROR;
720                                                                 }
721
722                                                                 if (reg2 == 32)
723                                                                         reg2 = 0;
724
725                                                                 parm = (WORD)(parm - 60 + 49);
726                                                         }
727                                                 }       
728                                         }
729                                 }
730                         }
731                         else
732                         {
733                                 reg2 = getregister(FU_REGTWO);
734                         }
735                 }
736
737                 if (*tok != ')')
738                         goto malformed;
739
740                 tok++;
741                 at_eol();
742                 risc_instruction_word(parm, reg2, reg1);
743                 break;
744
745         // LOADB/LOADP/LOADW (Rn),Rn
746         case RI_LOADN:                    
747                 if (*tok != '(')
748                         goto malformed;
749
750                 tok++;
751                 reg1 = getregister(FU_REGONE);
752
753                 if (*tok != ')')
754                         goto malformed;
755
756                 tok++;
757                 CHECK_COMMA;
758                 reg2 = getregister(FU_REGTWO);
759                 at_eol();
760                 risc_instruction_word(parm, reg1, reg2);
761                 break;
762
763         // STOREB/STOREP/STOREW Rn,(Rn)
764         case RI_STOREN:                   
765                 reg1 = getregister(FU_REGONE);
766                 CHECK_COMMA;
767
768                 if (*tok != '(')
769                         goto malformed;
770
771                 tok++;
772                 reg2 = getregister(FU_REGTWO);
773
774                 if (*tok != ')')
775                         goto malformed;
776
777                 tok++;
778                 at_eol();
779                 risc_instruction_word(parm, reg2, reg1);
780                 break;
781
782         case RI_JR:                       // Jump Relative - cc,n - n=-16..+15 words, reg2=cc
783         case RI_JUMP:                     // Jump Absolute - cc,(Rs) - reg2=cc
784                 // Check to see if there is a comma in the token string. If not then
785                 // the JR or JUMP should default to 0, Jump Always
786                 t = i = c = 0;
787
788                 while (t != EOL)
789                 {
790                         t = *(tok + i);
791
792                         if (t == ',')
793                                 c = 1;
794
795                         i++;
796                 }
797
798                 if (c)
799                 {
800                         // Comma present in token string
801                         if (*tok == CONST)
802                         {
803                                 // CC using a constant number
804                                 tok++;
805                                 val = *tok;
806                                 tok++;
807                                 CHECK_COMMA;
808                         }
809                         else if (*tok == SYMBOL)
810                         {
811                                 val = 99;
812 //                              strcpy(scratch, (char *)tok[1]);
813                                 strcpy(scratch, string[tok[1]]);
814                                 strtoupper(scratch);
815
816                                 for(i=0; i<MAXINTERNCC; i++)
817                                 {
818                                         // Look for the condition code & break if found
819                                         if (strcmp(condname[i], scratch) == 0)
820                                         {
821                                                 val = condnumber[i];
822                                                 break;
823                                         }
824                                 }
825
826                                 // Standard CC was not found, look for an equated one
827                                 if (val == 99)
828                                 {
829 //                                      ccsym = lookup((char *)tok[1], LABEL, 0);
830                                         ccsym = lookup(string[tok[1]], LABEL, 0);
831
832                                         if (ccsym && (ccsym->sattre & EQUATEDCC) && !(ccsym->sattre & UNDEF_CC))
833                                         {
834                                                 val = ccsym->svalue;
835                                         }
836                                         else
837                                         {
838                                                 error("unknown condition code");
839                                                 return ERROR;
840                                         }
841                                 }
842
843                                 tok += 2;
844                                 CHECK_COMMA;
845                         }
846                         else if (*tok == '(')
847                         {
848                                 // Jump always
849                                 val = 0;
850                         }
851                 }
852                 else
853                 {
854                         // Jump always
855                         val = 0;
856                 }
857
858                 if (val < 0 || val > 31)
859                 {
860                         error("condition constant out of range");
861                         return ERROR;
862                 }
863                 else
864                 {
865                         // Store condition code
866                         reg1 = val;
867                 }
868
869                 if (type == RI_JR)
870                 {
871                         // JR cc,n
872                         if (expr(r_expr, &eval, &eattr, &esym) != OK)
873                                 goto malformed;
874                         else
875                         {
876                                 tdb = (WORD)(eattr & TDB);
877                                 defined = (WORD)(eattr & DEFINED);
878
879                                 if ((challoc - ch_size) < 4)
880                                         chcheck(4L);
881
882                                 if (!defined)
883                                 {
884 #if 0
885                                         if (in_main)
886                                         {
887                                                 fixup(FU_WORD|FU_MJR, sloc, r_expr);
888                                         }
889                                         else
890 #endif
891 //                                      {
892                                                 fixup(FU_WORD | FU_JR, sloc, r_expr);
893 //                                      }
894
895                                         reg2 = 0;
896                                 }
897                                 else
898                                 {
899                                         val = eval;
900
901                                         if (orgactive)
902                                         {
903                                                 reg2 = ((int)(val - (orgaddr + 2))) / 2;
904
905                                                 if ((reg2 < -16) || (reg2 > 15))
906                                                         error("PC relative overflow");
907
908                                                 locptr = orgaddr;
909                                         }
910                                         else
911                                         {
912                                                 reg2 = ((int)(val - (sloc + 2))) / 2;
913
914                                                 if ((reg2 < -16) || (reg2 > 15))
915                                                         error("PC relative overflow");
916
917                                                 locptr = sloc;
918                                         }
919                                 }       
920
921 #if 0
922                                 if (in_main)
923                                 {
924                                         if (defined)
925                                         {
926                                                 if (((locptr >= 0xF03000) && (locptr < 0xF04000)
927                                                         && (val < 0xF03000)) || ((val >= 0xF03000)
928                                                         && (val < 0xF04000) && (locptr < 0xF03000)))
929                                                 {
930                                                         warn("* cannot jump relative between main memory and local gpu ram");
931                                                 }
932                                                 else
933                                                 {
934                                                         page_jump = (locptr & 0xFFFFFF00) - (val & 0xFFFFFF00);
935
936                                                         if (page_jump)
937                                                         {
938                                                                 if (val % 4)
939                                                                 {
940                                                                         warn("* destination address not aligned for long page jump relative, "
941                                                                         "insert a \'nop\' before the destination label/address");
942                                                                 }
943                                                         }
944                                                         else
945                                                         {
946                                                                 if ((val - 2) % 4)
947                                                                 {
948                                                                         warn("* destination address not aligned for short page jump relative, "
949                                                                                 "insert a \'nop\' before the destination label/address");
950                                                                 }
951                                                         }
952                                                 }
953                                         }
954                                 }
955 #endif
956                         }
957
958                         risc_instruction_word(parm, reg2, reg1);
959                 }
960                 else
961                 {
962                         // JUMP cc, (Rn)
963                         if (*tok != '(')
964                                 goto malformed;
965
966                         tok++;
967                         reg2 = getregister(FU_REGTWO);
968
969                         if (*tok != ')')
970                                 goto malformed;
971
972                         tok++;
973                         at_eol();
974
975 #if 0
976                         if (in_main)
977                         {
978                                 if (!mjump_align)
979                                 {
980                                         warn("* \'jump\' is not recommended for .gpumain as destination addresses "
981                                                 "cannot be validated for alignment, use \'mjump\'");
982                                         locptr = (orgactive) ? orgaddr : sloc;
983
984                                         if (locptr % 4)
985                                         {
986                                                 warn("* source address not aligned for long or short jump, "
987                                                         "insert a \'nop\' before the \'jump\'");
988                                         }          
989                                 }
990                                 else
991                                 {
992                                         if (mjump_defined)
993                                         {
994                                                 locptr = (orgactive) ? orgaddr : sloc;
995                                                 page_jump = (locptr & 0xFFFFFF00) - (mjump_dest & 0xFFFFFF00);
996
997                                                 if (page_jump)
998                                                 {
999                                                         if (mjump_dest % 4)
1000                                                         {
1001                                                                 warn("* destination address not aligned for long page jump, "
1002                                                                 "insert a \'nop\' before the destination label/address");
1003                                                         }          
1004                                                 }
1005                                                 else
1006                                                 {
1007                                                         if (!(mjump_dest & 0x0000000F) || ((mjump_dest - 2) % 4))
1008                                                         {
1009                                                                 warn("* destination address not aligned for short page jump, "
1010                                                                 "insert a \'nop\' before the destination label/address");
1011                                                         }          
1012                                                 }
1013                                         }
1014                                         else
1015                                         {
1016                                                 locptr = (orgactive) ? orgaddr : sloc;
1017                                                 fwdjump[fwindex++] = locptr;
1018                                         }
1019                                 }
1020                         }
1021 #endif
1022
1023                         risc_instruction_word(parm, reg2, reg1);
1024                 }
1025
1026                 break;
1027         // Should never get here :D
1028         default:                                              
1029                 error("unknown risc opcode type");
1030                 return ERROR;
1031                 break;
1032         }
1033
1034         return 0;
1035 }
1036