diff mbox

PATCH: PR target/59672: Add -m16 support for x86

Message ID 20140127194457.GA12183@intel.com
State New
Headers show

Commit Message

H.J. Lu Jan. 27, 2014, 7:44 p.m. UTC
Hi,

The .code16gcc directive was added to binutils back in 1999:

---
   '.code16gcc' provides experimental support for generating 16-bit code
from gcc, and differs from '.code16' in that 'call', 'ret', 'enter',
'leave', 'push', 'pop', 'pusha', 'popa', 'pushf', and 'popf'
instructions default to 32-bit size.  This is so that the stack pointer
is manipulated in the same way over function calls, allowing access to
function parameters at the same stack offsets as in 32-bit mode.
'.code16gcc' also automatically adds address size prefixes where
necessary to use the 32-bit addressing modes that gcc generates.
---

It encodes 32-bit assembly instructions generated by GCC in 16-bit format
 so that GCC can be used to generate 16-bit instructions.  To do that, the
 .code16gcc directive may be placed at the very beginning of the assembly
 code.  This patch adds -m16 to x86 backend by:

1. Add -m16 and make it mutually exclusive with -m32, -m64 and -mx32.
2. Treat -m16 like -m32 so that --32 is passed to assembler.
3. Output .code16gcc at the very beginning of the assembly code.
4. Turn off 64-bit ISA when -m16 is used.

Tested on Linux/x86 and Linux/x86-64.  OK for trunk?

Thanks.

H.J.
---
	PR target/59672
	* config/i386/gnu-user64.h (SPEC_32): Add "m16|" to "m32".
	(SPEC_X32): Likewise.
	(SPEC_64): Likewise.
	* config/i386/i386.c (ix86_option_override_internal): Turn off
	OPTION_MASK_ISA_64BIT, OPTION_MASK_ABI_X32 and OPTION_MASK_ABI_64
	for TARGET_16BIT.
	(x86_file_start): Output .code16gcc for TARGET_16BIT.
	* config/i386/i386.h (TARGET_16BIT): New macro.
	(TARGET_16BIT_P): Likewise.
	* config/i386/i386.opt: Add m16.
	* doc/invoke.texi: Document -m16.
---
 gcc/ChangeLog.m16            | 16 ++++++++++++++++
 gcc/config/i386/gnu-user64.h |  6 +++---
 gcc/config/i386/i386.c       |  6 ++++++
 gcc/config/i386/i386.h       |  2 ++
 gcc/config/i386/i386.opt     |  6 +++++-
 gcc/doc/invoke.texi          | 10 ++++++++--
 6 files changed, 40 insertions(+), 6 deletions(-)
 create mode 100644 gcc/ChangeLog.m16

Comments

Uros Bizjak Jan. 28, 2014, 4:01 p.m. UTC | #1
On Mon, Jan 27, 2014 at 8:44 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:

> The .code16gcc directive was added to binutils back in 1999:
>
> ---
>    '.code16gcc' provides experimental support for generating 16-bit code
> from gcc, and differs from '.code16' in that 'call', 'ret', 'enter',
> 'leave', 'push', 'pop', 'pusha', 'popa', 'pushf', and 'popf'
> instructions default to 32-bit size.  This is so that the stack pointer
> is manipulated in the same way over function calls, allowing access to
> function parameters at the same stack offsets as in 32-bit mode.
> '.code16gcc' also automatically adds address size prefixes where
> necessary to use the 32-bit addressing modes that gcc generates.
> ---
>
> It encodes 32-bit assembly instructions generated by GCC in 16-bit format
>  so that GCC can be used to generate 16-bit instructions.  To do that, the
>  .code16gcc directive may be placed at the very beginning of the assembly
>  code.  This patch adds -m16 to x86 backend by:
>
> 1. Add -m16 and make it mutually exclusive with -m32, -m64 and -mx32.
> 2. Treat -m16 like -m32 so that --32 is passed to assembler.
> 3. Output .code16gcc at the very beginning of the assembly code.
> 4. Turn off 64-bit ISA when -m16 is used.
>
> Tested on Linux/x86 and Linux/x86-64.  OK for trunk?
>
> Thanks.
>
> H.J.
> ---
>         PR target/59672
>         * config/i386/gnu-user64.h (SPEC_32): Add "m16|" to "m32".
>         (SPEC_X32): Likewise.
>         (SPEC_64): Likewise.
>         * config/i386/i386.c (ix86_option_override_internal): Turn off
>         OPTION_MASK_ISA_64BIT, OPTION_MASK_ABI_X32 and OPTION_MASK_ABI_64
>         for TARGET_16BIT.
>         (x86_file_start): Output .code16gcc for TARGET_16BIT.
>         * config/i386/i386.h (TARGET_16BIT): New macro.
>         (TARGET_16BIT_P): Likewise.
>         * config/i386/i386.opt: Add m16.
>         * doc/invoke.texi: Document -m16.

OK for mainline, needs OK from RMs for a backport.

Please also add the entry to Changes.html, this is user-visible change.

Thanks,
Uros.
Uros Bizjak Jan. 28, 2014, 4:30 p.m. UTC | #2
On Tue, Jan 28, 2014 at 5:01 PM, Uros Bizjak <ubizjak@gmail.com> wrote:
> On Mon, Jan 27, 2014 at 8:44 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:
>
>> The .code16gcc directive was added to binutils back in 1999:
>>
>> ---
>>    '.code16gcc' provides experimental support for generating 16-bit code
>> from gcc, and differs from '.code16' in that 'call', 'ret', 'enter',
>> 'leave', 'push', 'pop', 'pusha', 'popa', 'pushf', and 'popf'
>> instructions default to 32-bit size.  This is so that the stack pointer
>> is manipulated in the same way over function calls, allowing access to
>> function parameters at the same stack offsets as in 32-bit mode.
>> '.code16gcc' also automatically adds address size prefixes where
>> necessary to use the 32-bit addressing modes that gcc generates.
>> ---
>>
>> It encodes 32-bit assembly instructions generated by GCC in 16-bit format
>>  so that GCC can be used to generate 16-bit instructions.  To do that, the
>>  .code16gcc directive may be placed at the very beginning of the assembly
>>  code.  This patch adds -m16 to x86 backend by:
>>
>> 1. Add -m16 and make it mutually exclusive with -m32, -m64 and -mx32.
>> 2. Treat -m16 like -m32 so that --32 is passed to assembler.
>> 3. Output .code16gcc at the very beginning of the assembly code.
>> 4. Turn off 64-bit ISA when -m16 is used.
>>
>> Tested on Linux/x86 and Linux/x86-64.  OK for trunk?
>>
>> Thanks.
>>
>> H.J.
>> ---
>>         PR target/59672
>>         * config/i386/gnu-user64.h (SPEC_32): Add "m16|" to "m32".
>>         (SPEC_X32): Likewise.
>>         (SPEC_64): Likewise.
>>         * config/i386/i386.c (ix86_option_override_internal): Turn off
>>         OPTION_MASK_ISA_64BIT, OPTION_MASK_ABI_X32 and OPTION_MASK_ABI_64
>>         for TARGET_16BIT.
>>         (x86_file_start): Output .code16gcc for TARGET_16BIT.
>>         * config/i386/i386.h (TARGET_16BIT): New macro.
>>         (TARGET_16BIT_P): Likewise.
>>         * config/i386/i386.opt: Add m16.
>>         * doc/invoke.texi: Document -m16.
>
> OK for mainline, needs OK from RMs for a backport.
>
> Please also add the entry to Changes.html, this is user-visible change.

Oh, a short scan-asm testcase would be nice, too.

Thanks,
Uros.
Richard Biener Jan. 29, 2014, 9:52 a.m. UTC | #3
On Tue, 28 Jan 2014, Uros Bizjak wrote:

> On Mon, Jan 27, 2014 at 8:44 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> 
> > The .code16gcc directive was added to binutils back in 1999:
> >
> > ---
> >    '.code16gcc' provides experimental support for generating 16-bit code
> > from gcc, and differs from '.code16' in that 'call', 'ret', 'enter',
> > 'leave', 'push', 'pop', 'pusha', 'popa', 'pushf', and 'popf'
> > instructions default to 32-bit size.  This is so that the stack pointer
> > is manipulated in the same way over function calls, allowing access to
> > function parameters at the same stack offsets as in 32-bit mode.
> > '.code16gcc' also automatically adds address size prefixes where
> > necessary to use the 32-bit addressing modes that gcc generates.
> > ---
> >
> > It encodes 32-bit assembly instructions generated by GCC in 16-bit format
> >  so that GCC can be used to generate 16-bit instructions.  To do that, the
> >  .code16gcc directive may be placed at the very beginning of the assembly
> >  code.  This patch adds -m16 to x86 backend by:
> >
> > 1. Add -m16 and make it mutually exclusive with -m32, -m64 and -mx32.
> > 2. Treat -m16 like -m32 so that --32 is passed to assembler.
> > 3. Output .code16gcc at the very beginning of the assembly code.
> > 4. Turn off 64-bit ISA when -m16 is used.
> >
> > Tested on Linux/x86 and Linux/x86-64.  OK for trunk?
> >
> > Thanks.
> >
> > H.J.
> > ---
> >         PR target/59672
> >         * config/i386/gnu-user64.h (SPEC_32): Add "m16|" to "m32".
> >         (SPEC_X32): Likewise.
> >         (SPEC_64): Likewise.
> >         * config/i386/i386.c (ix86_option_override_internal): Turn off
> >         OPTION_MASK_ISA_64BIT, OPTION_MASK_ABI_X32 and OPTION_MASK_ABI_64
> >         for TARGET_16BIT.
> >         (x86_file_start): Output .code16gcc for TARGET_16BIT.
> >         * config/i386/i386.h (TARGET_16BIT): New macro.
> >         (TARGET_16BIT_P): Likewise.
> >         * config/i386/i386.opt: Add m16.
> >         * doc/invoke.texi: Document -m16.
> 
> OK for mainline, needs OK from RMs for a backport.

I don't think this is suitable for the branch.  Unless there is
tremendous need for it somewhere ...?  I like the suggested
addition of a --code16gcc assembler flag.  Please make sure to
document the minimum required binutils to make this work.

Richard.
H.J. Lu Jan. 29, 2014, 1:57 p.m. UTC | #4
On Wed, Jan 29, 2014 at 1:52 AM, Richard Biener <rguenther@suse.de> wrote:
> On Tue, 28 Jan 2014, Uros Bizjak wrote:
>
>> On Mon, Jan 27, 2014 at 8:44 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:
>>
>> > The .code16gcc directive was added to binutils back in 1999:
>> >
>> > ---
>> >    '.code16gcc' provides experimental support for generating 16-bit code
>> > from gcc, and differs from '.code16' in that 'call', 'ret', 'enter',
>> > 'leave', 'push', 'pop', 'pusha', 'popa', 'pushf', and 'popf'
>> > instructions default to 32-bit size.  This is so that the stack pointer
>> > is manipulated in the same way over function calls, allowing access to
>> > function parameters at the same stack offsets as in 32-bit mode.
>> > '.code16gcc' also automatically adds address size prefixes where
>> > necessary to use the 32-bit addressing modes that gcc generates.
>> > ---
>> >
>> > It encodes 32-bit assembly instructions generated by GCC in 16-bit format
>> >  so that GCC can be used to generate 16-bit instructions.  To do that, the
>> >  .code16gcc directive may be placed at the very beginning of the assembly
>> >  code.  This patch adds -m16 to x86 backend by:
>> >
>> > 1. Add -m16 and make it mutually exclusive with -m32, -m64 and -mx32.
>> > 2. Treat -m16 like -m32 so that --32 is passed to assembler.
>> > 3. Output .code16gcc at the very beginning of the assembly code.
>> > 4. Turn off 64-bit ISA when -m16 is used.
>> >
>> > Tested on Linux/x86 and Linux/x86-64.  OK for trunk?
>> >
>> > Thanks.
>> >
>> > H.J.
>> > ---
>> >         PR target/59672
>> >         * config/i386/gnu-user64.h (SPEC_32): Add "m16|" to "m32".
>> >         (SPEC_X32): Likewise.
>> >         (SPEC_64): Likewise.
>> >         * config/i386/i386.c (ix86_option_override_internal): Turn off
>> >         OPTION_MASK_ISA_64BIT, OPTION_MASK_ABI_X32 and OPTION_MASK_ABI_64
>> >         for TARGET_16BIT.
>> >         (x86_file_start): Output .code16gcc for TARGET_16BIT.
>> >         * config/i386/i386.h (TARGET_16BIT): New macro.
>> >         (TARGET_16BIT_P): Likewise.
>> >         * config/i386/i386.opt: Add m16.
>> >         * doc/invoke.texi: Document -m16.
>>
>> OK for mainline, needs OK from RMs for a backport.
>
> I don't think this is suitable for the branch.  Unless there is
> tremendous need for it somewhere ...?  I like the suggested

Linux kernel people want it and clang has it.

> addition of a --code16gcc assembler flag.  Please make sure to
> document the minimum required binutils to make this work.
>

Since the .code16gcc directive was added to binutils back in 1999,
it is older than the minimum binutils required for x86 GCC.  There
is no need to specify a separate minimum binutils for it.
Alexander Monakov Jan. 29, 2014, 2:41 p.m. UTC | #5
On Wed, 29 Jan 2014, H.J. Lu wrote:
> Since the .code16gcc directive was added to binutils back in 1999,
> it is older than the minimum binutils required for x86 GCC.  There
> is no need to specify a separate minimum binutils for it.

It's not clear to me why the compiler should be involved in providing this
functionality.  Can the assembler simply support '-mcode16gcc' command-line
flag, which would have the effect of enabling .code16gcc for the whole
translation unit?  That way, you could simply add -Wa,-mcode16gcc to the GCC
command line and avoid the need to patch the compiler.  Am I missing
something?

Thanks.

Alexander
H.J. Lu Jan. 29, 2014, 4:39 p.m. UTC | #6
On Wed, Jan 29, 2014 at 6:41 AM, Alexander Monakov <amonakov@ispras.ru> wrote:
>
> On Wed, 29 Jan 2014, H.J. Lu wrote:
>> Since the .code16gcc directive was added to binutils back in 1999,
>> it is older than the minimum binutils required for x86 GCC.  There
>> is no need to specify a separate minimum binutils for it.
>
> It's not clear to me why the compiler should be involved in providing this
> functionality.  Can the assembler simply support '-mcode16gcc' command-line
> flag, which would have the effect of enabling .code16gcc for the whole
> translation unit?  That way, you could simply add -Wa,-mcode16gcc to the GCC
> command line and avoid the need to patch the compiler.  Am I missing
> something?

-m16 is used by Linux kernel, which checks if the compiler supports -m16
and uses it if it does. Adding gas --code16gcc check is an additional change
in Linux kernel.  Clang already supports -m16, which generates objects
directly.  Adding gas --code16gcc check doesn't help clang.  Add -m16
to gcc makes gcc and clang consistent to Linux kernel build.
Jakub Jelinek Jan. 29, 2014, 4:52 p.m. UTC | #7
On Wed, Jan 29, 2014 at 08:39:55AM -0800, H.J. Lu wrote:
> -m16 is used by Linux kernel, which checks if the compiler supports -m16
> and uses it if it does. Adding gas --code16gcc check is an additional change
> in Linux kernel.  Clang already supports -m16, which generates objects
> directly.  Adding gas --code16gcc check doesn't help clang.  Add -m16
> to gcc makes gcc and clang consistent to Linux kernel build.

Not everything clang/llvm comes up with is a good idea to follow (numerous
examples in mind, won't list them here, don't want to start a flamewar).
Given that .code16gcc is really a hack in the assembler, I really think it
would be much better idea to just let kernel use -Wa,--code16gcc for this hack.
Sure, if somebody started a full-blown 16-bit code generation support as
opposed to .code16gcc, -m16 would make sense (unless it would be a separate
backend).

	Jakub
H.J. Lu Jan. 29, 2014, 5:01 p.m. UTC | #8
On Wed, Jan 29, 2014 at 8:52 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Jan 29, 2014 at 08:39:55AM -0800, H.J. Lu wrote:
>> -m16 is used by Linux kernel, which checks if the compiler supports -m16
>> and uses it if it does. Adding gas --code16gcc check is an additional change
>> in Linux kernel.  Clang already supports -m16, which generates objects
>> directly.  Adding gas --code16gcc check doesn't help clang.  Add -m16
>> to gcc makes gcc and clang consistent to Linux kernel build.
>
> Not everything clang/llvm comes up with is a good idea to follow (numerous
> examples in mind, won't list them here, don't want to start a flamewar).
> Given that .code16gcc is really a hack in the assembler, I really think it
> would be much better idea to just let kernel use -Wa,--code16gcc for this hack.
> Sure, if somebody started a full-blown 16-bit code generation support as
> opposed to .code16gcc, -m16 would make sense (unless it would be a separate
> backend).

As for as Linux kernel is concerned, they want -m16 to generate 16-bit codes
from C source, .code16gcc or a separate 16-bit backend make no difference
to them.
diff mbox

Patch

diff --git a/gcc/ChangeLog.m16 b/gcc/ChangeLog.m16
new file mode 100644
index 0000000..05424d9
--- /dev/null
+++ b/gcc/ChangeLog.m16
@@ -0,0 +1,16 @@ 
+gcc/
+
+2014-01-23  H.J. Lu  <hongjiu.lu@intel.com>
+
+	PR target/59672
+	* config/i386/gnu-user64.h (SPEC_32): Add "m16|" to "m32".
+	(SPEC_X32): Likewise.
+	(SPEC_64): Likewise.
+	* config/i386/i386.c (ix86_option_override_internal): Turn off
+	OPTION_MASK_ISA_64BIT, OPTION_MASK_ABI_X32 and OPTION_MASK_ABI_64
+	for TARGET_16BIT.
+	(x86_file_start): Output .code16gcc for TARGET_16BIT.
+	* config/i386/i386.h (TARGET_16BIT): New macro.
+	(TARGET_16BIT_P): Likewise.
+	* config/i386/i386.opt: Add m16.
+	* doc/invoke.texi: Document -m16.
diff --git a/gcc/config/i386/gnu-user64.h b/gcc/config/i386/gnu-user64.h
index 8d33483..1c72b41 100644
--- a/gcc/config/i386/gnu-user64.h
+++ b/gcc/config/i386/gnu-user64.h
@@ -32,12 +32,12 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    done.  */
 
 #if TARGET_64BIT_DEFAULT
-#define SPEC_32 "m32"
+#define SPEC_32 "m16|m32"
 #if TARGET_BI_ARCH == 2
 #define SPEC_64 "m64"
-#define SPEC_X32 "m32|m64:;"
+#define SPEC_X32 "m16|m32|m64:;"
 #else
-#define SPEC_64 "m32|mx32:;"
+#define SPEC_64 "m16|m32|mx32:;"
 #define SPEC_X32 "mx32"
 #endif
 #else
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index cf79486..c132cd9 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3342,6 +3342,10 @@  ix86_option_override_internal (bool main_args_p,
       opts->x_ix86_isa_flags |= OPTION_MASK_ISA_64BIT;
       opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_64;
     }
+  else if (TARGET_16BIT_P (opts->x_ix86_isa_flags))
+    opts->x_ix86_isa_flags &= ~(OPTION_MASK_ISA_64BIT
+				| OPTION_MASK_ABI_X32
+				| OPTION_MASK_ABI_64);
   else if (TARGET_LP64_P (opts->x_ix86_isa_flags))
     {
       /* Always turn on OPTION_MASK_ISA_64BIT and turn off
@@ -38815,6 +38819,8 @@  static void
 x86_file_start (void)
 {
   default_file_start ();
+  if (TARGET_16BIT)
+    fputs ("\t.code16gcc\n", asm_out_file);
 #if TARGET_MACHO
   darwin_file_start ();
 #endif
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 580a319..bfb6dc6 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -135,6 +135,8 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_LP64_P(x)	TARGET_ABI_64_P(x)
 #define TARGET_X32	TARGET_ABI_X32
 #define TARGET_X32_P(x)	TARGET_ABI_X32_P(x)
+#define TARGET_16BIT	TARGET_CODE16
+#define TARGET_16BIT_P(x)	TARGET_CODE16_P(x)
 
 /* SSE4.1 defines round instructions */
 #define	OPTION_MASK_ISA_ROUND	OPTION_MASK_ISA_SSE4_1
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 26cd8bb..485ed2a 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -558,9 +558,13 @@  Target RejectNegative Negative(mx32) Report Mask(ABI_64) Var(ix86_isa_flags) Sav
 Generate 64bit x86-64 code
 
 mx32
-Target RejectNegative Negative(m32) Report Mask(ABI_X32) Var(ix86_isa_flags) Save
+Target RejectNegative Negative(m16) Report Mask(ABI_X32) Var(ix86_isa_flags) Save
 Generate 32bit x86-64 code
 
+m16
+Target RejectNegative Negative(m32) Report Mask(CODE16) InverseMask(ISA_64BIT) Var(ix86_isa_flags) Save
+Generate 16bit i386 code
+
 mmmx
 Target Report Mask(ISA_MMX) Var(ix86_isa_flags) Save
 Support MMX built-in functions
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8c620a5..c87f08b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -680,7 +680,7 @@  Objective-C and Objective-C++ Dialects}.
 -mpc32 -mpc64 -mpc80 -mstackrealign @gol
 -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs @gol
 -mcmodel=@var{code-model} -mabi=@var{name} -maddress-mode=@var{mode} @gol
--m32 -m64 -mx32 -mlarge-data-threshold=@var{num} @gol
+-m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol
 -msse2avx -mfentry -m8bit-idiv @gol
 -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
 -mstack-protector-guard=@var{guard}}
@@ -15635,10 +15635,12 @@  on x86-64 processors in 64-bit environments.
 @item -m32
 @itemx -m64
 @itemx -mx32
+@itemx -m16
 @opindex m32
 @opindex m64
 @opindex mx32
-Generate code for a 32-bit or 64-bit environment.
+@opindex m16
+Generate code for a 16-bit, 32-bit or 64-bit environment.
 The @option{-m32} option sets @code{int}, @code{long}, and pointer types
 to 32 bits, and
 generates code that runs on any i386 system.
@@ -15652,6 +15654,10 @@  The @option{-mx32} option sets @code{int}, @code{long}, and pointer types
 to 32 bits, and
 generates code for the x86-64 architecture.
 
+The @option{-m16} option is the same as @option{-m32}, except for that
+it outputs the @code{.code16gcc} assembly directive at the beginning of
+the assembly output so that the binary can run in 16-bit mode.
+
 @item -mno-red-zone
 @opindex mno-red-zone
 Do not use a so-called ``red zone'' for x86-64 code.  The red zone is mandated