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