This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] S/390: Automatic mnemonic extensions for conditional jumps


Hello,

on S/390 instructions depending on the condition code use a 4 bit
condition code mask operand to specify which bits of the condition
code are relevant.  For readability purposes we expand such an
instruction to a set of instructions which instead of the condition
code mask operand have a mnemonic extension which express the current
meaning of the condition code.

So besides the

brc 7, 20   (7 is the conditional mask operand and 20 the jump target)

instruction we also provide mnemonics like

jne 20

and

jnz 20

which represent exactly the same opcode.  Unfortunately this leads to
a lot of lines in the mnemonics list which could easily be generated
by s390-mkopc.  And this is what the attached patch does.  A mnemonic
like j*8 is expanded to all the 20 variants which represent the
respective condition code masks.  The number behind the '*' special
char specifies the bit number in the opcode where the conditional mask
operand has to be inserted.

This also works for mnemonics where the conditional extension has to
be inserted somewhere in the middle of the mnemonic like for b*8r
(bcr) which is expanded to bner bnzr ... .

Tested on s390 and s390x. No testsuite fails.

Ok to apply?

Bye,

-Andreas-


2007-08-21  Andreas Krebbel  <krebbel1@de.ibm.com>

	* opcodes/s390-mkopc.c (struct s390_cond_ext_format): New
	global struct.
	(s390_cond_ext_format): New global variable.
	(expandConditionalJump): New function.
	(main): Invoke expandConditionalJump for mnemonics containing '*'.	
	* opcodes/s390-opc.txt: Replace mnemonics with conditional
	mask extensions with instructions using the newly introduced
	'*' tag.


Index: opcodes/s390-mkopc.c
===================================================================
*** opcodes/s390-mkopc.c.orig	2007-08-16 15:18:24.000000000 +0200
--- opcodes/s390-mkopc.c	2007-08-21 13:48:15.000000000 +0200
*************** insertOpcode (char *opcode, char *mnemon
*** 115,120 ****
--- 115,237 ----
    no_ops++;
  }
  
+ struct s390_cond_ext_format
+ {
+   char nibble;
+   char extension[4];
+ };
+ 
+ #define NUM_COND_EXTENSIONS 20
+ 
+ const struct s390_cond_ext_format s390_cond_extensions[NUM_COND_EXTENSIONS] =
+   {
+     { '1', "o" },    /* jump on overflow / if ones */
+     { '2', "h" },    /* jump on A high */
+     { '2', "p" },    /* jump on plus */
+     { '3', "nle" },  /* jump on not low or equal */
+     { '4', "l" },    /* jump on A low */
+     { '4', "m" },    /* jump on minus / if mixed */
+     { '5', "nhe" },  /* jump on not high or equal */
+     { '6', "lh" },   /* jump on low or high */
+     { '7', "ne" },   /* jump on A not equal B */
+     { '7', "nz" },   /* jump on not zero / if not zeros */
+     { '8', "e" },    /* jump on A equal B */
+     { '8', "z" },    /* jump on zero / if zeros */
+     { '9', "nlh" },  /* jump on not low or high */
+     { 'a', "he" },   /* jump on high or equal */
+     { 'b', "nl" },   /* jump on A not low */
+     { 'b', "nm" },   /* jump on not minus / if not mixed */
+     { 'c', "le" },   /* jump on low or equal */
+     { 'd', "nh" },   /* jump on A not high */
+     { 'd', "np" },   /* jump on not plus */
+     { 'e', "no" },   /* jump on not overflow / if not ones */
+   };
+ 
+ /* As with insertOpcode instructions are added to the sorted opcode
+    array.  Additionally mnemonics containing the '*<number>' tag are
+    expanded to the set of conditional instructions described by
+    s390_cond_extensions with the '*<number>' tag replaced by the
+    respective mnemonic extensions.  */
+ 
+ static void
+ expandConditionalJump (char *opcode, char *mnemonic, char *format,
+ 		       int min_cpu, int mode_bits)
+ {
+   char prefix[5];
+   char suffix[5];
+   char number[5];
+   int mask_start, i = 0, star_found = 0, reading_number = 0;
+   int number_p = 0, suffix_p = 0, prefix_p = 0;
+ 
+   while (mnemonic[i] != '\0')
+     {
+       switch (mnemonic[i])
+ 	{
+ 	case '*':
+ 	  if (star_found)
+ 	    goto malformed_mnemonic;
+ 
+ 	  star_found = 1;
+ 	  reading_number = 1;
+ 	  break;
+ 
+ 	case '0': case '1': case '2': case '3': case '4':
+ 	case '5': case '6': case '7': case '8': case '9':
+ 	  if (!star_found || !reading_number)
+ 	    goto malformed_mnemonic;
+ 
+ 	  number[number_p++] = mnemonic[i];
+ 	  break;
+ 
+ 	default:
+ 	  if (reading_number)
+ 	    {
+ 	      if (!number_p)
+ 		goto malformed_mnemonic;
+ 	      else
+ 		reading_number = 0;
+ 	    }
+ 
+ 	  if (star_found)
+ 	    suffix[suffix_p++] = mnemonic[i];
+ 	  else
+ 	    prefix[prefix_p++] = mnemonic[i];
+ 	}
+       i++;
+     }
+ 
+   prefix[prefix_p] = '\0';
+   suffix[suffix_p] = '\0';
+   number[number_p] = '\0';
+ 
+   if (sscanf (number, "%d", &mask_start) != 1)
+     goto malformed_mnemonic;
+ 
+   if (mask_start & 3)
+     {
+       fprintf (stderr, "Conditional mask not at nibble boundary in: %s\n",
+ 	       mnemonic);
+       return;
+     }
+ 
+   mask_start >>= 2;
+ 
+   for (i = 0; i < NUM_COND_EXTENSIONS; i++)
+     {
+       char new_mnemonic[15];
+ 
+       strcpy (new_mnemonic, prefix);
+       strcat (new_mnemonic, s390_cond_extensions[i].extension);
+       strcat (new_mnemonic, suffix);
+       opcode[mask_start] = s390_cond_extensions[i].nibble;
+       insertOpcode (opcode, new_mnemonic, format, min_cpu, mode_bits);
+     }
+   return;
+ 
+  malformed_mnemonic:
+   fprintf (stderr, "Malformed mnemonic: %s\n", mnemonic);
+ }
+ 
  static char file_header[] =
    "/* The opcode table. This file was generated by s390-mkopc.\n\n"
    "   The format of the opcode table is:\n\n"
*************** main (void)
*** 225,231 ****
  	    if (*str == ',')
  	      str++;
  	  } while (*str != 0);
! 	  insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits);
  	}
        else
          fprintf (stderr, "Couldn't scan line %s\n", currentLine);
--- 342,353 ----
  	    if (*str == ',')
  	      str++;
  	  } while (*str != 0);
! 
! 	  if (!strchr (mnemonic, '*'))
! 	    insertOpcode (opcode, mnemonic, format, min_cpu, mode_bits);
! 	  else
! 	    expandConditionalJump (opcode, mnemonic, format,
! 				   min_cpu, mode_bits);
  	}
        else
          fprintf (stderr, "Couldn't scan line %s\n", currentLine);
Index: opcodes/s390-opc.txt
===================================================================
*** opcodes/s390-opc.txt.orig	2007-08-16 15:21:08.000000000 +0200
--- opcodes/s390-opc.txt	2007-08-21 13:48:15.000000000 +0200
*************** b252 msr RRE_RR "multiply single" g5 esa
*** 262,331 ****
  a700 tmh RI_RU "test under mask high" g5 esa,zarch
  a701 tml RI_RU "test under mask low" g5 esa,zarch
  0700 nopr RR_0R "no operation" g5 esa,zarch
! 0710 bor RR_0R "branch on overflow / if ones" g5 esa,zarch
! 0720 bhr RR_0R "branch on high" g5 esa,zarch
! 0720 bpr RR_0R "branch on plus" g5 esa,zarch
! 0730 bnler RR_0R "branch on not low or equal" g5 esa,zarch
! 0740 blr RR_0R "branch on low" g5 esa,zarch
! 0740 bmr RR_0R "branch on minus / if mixed" g5 esa,zarch
! 0750 bnher RR_0R "branch on not high or equal" g5 esa,zarch
! 0760 blhr RR_0R "branch on low or high" g5 esa,zarch
! 0770 bner RR_0R "branch on not equal" g5 esa,zarch
! 0770 bnzr RR_0R "branch on not zero / if not zeros" g5 esa,zarch
! 0780 ber RR_0R "branch on equal" g5 esa,zarch
! 0780 bzr RR_0R "branch on zero / if zeros" g5 esa,zarch
! 0790 bnlhr RR_0R "branch on not low or high" g5 esa,zarch
! 07a0 bher RR_0R "branch on high or equal" g5 esa,zarch
! 07b0 bnlr RR_0R "branch on not low" g5 esa,zarch
! 07b0 bnmr RR_0R "branch on not minus / if not mixed" g5 esa,zarch
! 07c0 bler RR_0R "brach on low or equal" g5 esa,zarch
! 07d0 bnhr RR_0R "branch on not high" g5 esa,zarch
! 07d0 bnpr RR_0R "branch on not plus" g5 esa,zarch
! 07e0 bnor RR_0R "branch on not overflow / if not ones" g5 esa,zarch
  07f0 br RR_0R "unconditional branch" g5 esa,zarch
  4700 nop RX_0RRD "no operation" g5 esa,zarch
! 4710 bo RX_0RRD "branch on overflow / if ones" g5 esa,zarch
! 4720 bh RX_0RRD "branch on high" g5 esa,zarch
! 4720 bp RX_0RRD "branch on plus" g5 esa,zarch
! 4730 bnle RX_0RRD "branch on not low or equal" g5 esa,zarch
! 4740 bl RX_0RRD "branch on low" g5 esa,zarch
! 4740 bm RX_0RRD "branch on minus / if mixed" g5 esa,zarch
! 4750 bnhe RX_0RRD "branch on not high or equal" g5 esa,zarch
! 4760 blh RX_0RRD "branch on low or high" g5 esa,zarch
! 4770 bne RX_0RRD "branch on not equal" g5 esa,zarch
! 4770 bnz RX_0RRD "branch on not zero / if not zeros" g5 esa,zarch
! 4780 be RX_0RRD "branch on equal" g5 esa,zarch
! 4780 bz RX_0RRD "branch on zero / if zeros" g5 esa,zarch
! 4790 bnlh RX_0RRD "branch on not low or high" g5 esa,zarch
! 47a0 bhe RX_0RRD "branch on high or equal" g5 esa,zarch
! 47b0 bnl RX_0RRD "branch on not low" g5 esa,zarch
! 47b0 bnm RX_0RRD "branch on not minus / if not mixed" g5 esa,zarch
! 47c0 ble RX_0RRD "branch on low or equal" g5 esa,zarch
! 47d0 bnh RX_0RRD "branch on not high" g5 esa,zarch
! 47d0 bnp RX_0RRD "branch on not plus" g5 esa,zarch
! 47e0 bno RX_0RRD "branch on not overflow / if not ones" g5 esa,zarch
  47f0 b RX_0RRD "unconditional branch" g5 esa,zarch
! a714 jo RI_0P "jump on overflow / if ones" g5 esa,zarch
! a724 jh RI_0P "jump on A high" g5 esa,zarch
! a724 jp RI_0P "jump on plus" g5 esa,zarch
! a734 jnle RI_0P "jump on not low or equal" g5 esa,zarch
! a744 jl RI_0P "jump on A low" g5 esa,zarch
! a744 jm RI_0P "jump on minus / if mixed" g5 esa,zarch
! a754 jnhe RI_0P "jump on not high or equal" g5 esa,zarch
! a764 jlh RI_0P "jump on low or high" g5 esa,zarch
! a774 jne RI_0P "jump on A not equal B" g5 esa,zarch
! a774 jnz RI_0P "jump on not zero / if not zeros" g5 esa,zarch
! a784 je RI_0P "jump on A equal B" g5 esa,zarch
! a784 jz RI_0P "jump on zero / if zeros" g5 esa,zarch
! a794 jnlh RI_0P "jump on not low or high" g5 esa,zarch
! a7a4 jhe RI_0P "jump on high or equal" g5 esa,zarch
! a7b4 jnl RI_0P "jump on A not low" g5 esa,zarch
! a7b4 jnm RI_0P "jump on not minus / if not mixed" g5 esa,zarch
! a7c4 jle RI_0P "jump on low or equal" g5 esa,zarch
! a7d4 jnh RI_0P "jump on A not high" g5 esa,zarch
! a7d4 jnp RI_0P "jump on not plus" g5 esa,zarch
! a7e4 jno RI_0P "jump on not overflow / if not ones" g5 esa,zarch
! a7f4 j RI_0P "jump" g5 esa,zarch
  b34a axbr RRE_FF "add extended bfp" g5 esa,zarch
  b31a adbr RRE_FF "add long bfp" g5 esa,zarch
  ed000000001a adb RXE_FRRD "add long bfp" g5 esa,zarch
--- 262,274 ----
  a700 tmh RI_RU "test under mask high" g5 esa,zarch
  a701 tml RI_RU "test under mask low" g5 esa,zarch
  0700 nopr RR_0R "no operation" g5 esa,zarch
! 0700 b*8r RR_0R "conditional branch" g5 esa,zarch
  07f0 br RR_0R "unconditional branch" g5 esa,zarch
  4700 nop RX_0RRD "no operation" g5 esa,zarch
! 4700 b*8 RX_0RRD "conditional branch" g5 esa,zarch
  47f0 b RX_0RRD "unconditional branch" g5 esa,zarch
! a704 j*8 RI_0P "conditional jump" g5 esa,zarch
! a7f4 j RI_0P "unconditional jump" g5 esa,zarch
  b34a axbr RRE_FF "add extended bfp" g5 esa,zarch
  b31a adbr RRE_FF "add long bfp" g5 esa,zarch
  ed000000001a adb RXE_FRRD "add long bfp" g5 esa,zarch
*************** eb0000000080 icmh RSE_RURD "insert chara
*** 520,546 ****
  a702 tmhh RI_RU "test under mask high high" z900 zarch
  a703 tmhl RI_RU "test under mask high low" z900 zarch
  c004 brcl RIL_UP "branch relative on condition long" z900 esa,zarch
! c014 jgo RIL_0P "jump long on overflow / if ones" z900 esa,zarch
! c024 jgh RIL_0P "jump long on high" z900 esa,zarch
! c024 jgp RIL_0P "jump long on plus" z900 esa,zarch
! c034 jgnle RIL_0P "jump long on not low or equal" z900 esa,zarch
! c044 jgl RIL_0P "jump long on low" z900 esa,zarch
! c044 jgm RIL_0P "jump long on minus / if mixed" z900 esa,zarch
! c054 jgnhe RIL_0P "jump long on not high or equal" z900 esa,zarch
! c064 jglh RIL_0P "jump long on low or high" z900 esa,zarch
! c074 jgne RIL_0P "jump long on not equal" z900 esa,zarch
! c074 jgnz RIL_0P "jump long on not zero / if not zeros" z900 esa,zarch
! c084 jge RIL_0P "jump long on equal" z900 esa,zarch
! c084 jgz RIL_0P "jump long on zero / if zeros" z900 esa,zarch
! c094 jgnlh RIL_0P "jump long on not low or high" z900 esa,zarch
! c0a4 jghe RIL_0P "jump long on high or equal" z900 esa,zarch
! c0b4 jgnl RIL_0P "jump long on not low" z900 esa,zarch
! c0b4 jgnm RIL_0P "jump long on not minus / if not mixed" z900 esa,zarch
! c0c4 jgle RIL_0P "jump long on low or equal" z900 esa,zarch
! c0d4 jgnh RIL_0P "jump long on not high" z900 esa,zarch
! c0d4 jgnp RIL_0P "jump long on not plus" z900 esa,zarch
! c0e4 jgno RIL_0P "jump long on not overflow / if not ones" z900 esa,zarch
! c0f4 jg RIL_0P "jump long" z900 esa,zarch
  c005 brasl RIL_RP "branch relative and save long" z900 esa,zarch
  a707 brctg RI_RP "branch relative on count 64" z900 zarch
  a709 lghi RI_RI "load halfword immediate 64" z900 zarch
--- 463,470 ----
  a702 tmhh RI_RU "test under mask high high" z900 zarch
  a703 tmhl RI_RU "test under mask high low" z900 zarch
  c004 brcl RIL_UP "branch relative on condition long" z900 esa,zarch
! c004 jg*8 RIL_0P "conditional jump long" z900 esa,zarch
! c0f4 jg RIL_0P "unconditional jump long" z900 esa,zarch
  c005 brasl RIL_RP "branch relative and save long" z900 esa,zarch
  a707 brctg RI_RP "branch relative on count 64" z900 zarch
  a709 lghi RI_RI "load halfword immediate 64" z900 zarch


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]