Mercurial > hg > CbC > old > device
changeset 731:1f6e34c4dbbf
INTEL64 (start)
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 29 Oct 2010 16:14:00 +0900 |
parents | 9bad72e27174 |
children | 7a4f389b5bc0 |
files | Makefile mc-code-i64.c mc-parse.c mc.h test/code-gen.c |
diffstat | 5 files changed, 4879 insertions(+), 62 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Fri Oct 29 16:13:47 2010 +0900 +++ b/Makefile Fri Oct 29 16:14:00 2010 +0900 @@ -10,7 +10,7 @@ BASE=0 STAGE=1 MFLAGS=$(MFALGS) BASE=$(BASE) STAGE=$(STAGE) -ARCH=ia32 +ARCH=i64 MC=mc-$(ARCH) MLIB = -lm PRINTF= # printf.c @@ -25,12 +25,18 @@ all: mc tags +predefined: + $(CC) -xc -E -dM /dev/null + ppc: make ARCH=powerpc CCEXT="-arch ppc" check-all mc: mc-$(ARCH) cp mc-$(ARCH) mc +mc-i64 :conv/conv.h mc-include.c mc-code-i64.o $(COMPLIB) $(CONVERTER) + $(CC) $(LDFLAGS) -g mc-code-i64.o $(COMPLIB) $(CONVERTER) -o $@ + mc-powerpc :conv/conv.h mc-include.c mc-code-powerpc.o $(COMPLIB) $(CONVERTER) $(CC) $(LDFLAGS) -g mc-code-powerpc.o $(COMPLIB) $(CONVERTER) -o $@ @@ -199,7 +205,6 @@ tags-$(ARCH): ctags mc.h mc-code.h mc-code-$(ARCH).c mc-codegen.c mc-codegen.h \ mc-parse.h mc-tree.c mc-inline.h mc-switch.h \ - mc-parse.c mc-tree.c mc-inline.c mc-switch.c \ mc-macro.h mc-macro.c \ conv/c.c conv/c.h \ conv/conv.h conv/convdef.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mc-code-i64.c Fri Oct 29 16:14:00 2010 +0900 @@ -0,0 +1,4809 @@ +/* Micro-C Code Generation Part for intel386 */ + +/************************************************************************ +** Copyright (C) 2006 Shinji Kono +** 連絡先: 琉球大学情報工学科 河野 真治 +** (E-Mail Address: kono@ie.u-ryukyu.ac.jp) +** +** このソースのいかなる複写,改変,修正も許諾します。ただし、 +** その際には、誰が貢献したを示すこの部分を残すこと。 +** 再配布や雑誌の付録などの問い合わせも必要ありません。 +** 営利利用も上記に反しない範囲で許可します。 +** バイナリの配布の際にはversion messageを保存することを条件とします。 +** このプログラムについては特に何の保証もしない、悪しからず。 +** +** Everyone is permitted to do anything on this program +** including copying, modifying, improving, +** as long as you don't try to pretend that you wrote it. +** i.e., the above copyright notice has to appear in all copies. +** Binary distribution requires original version messages. +** You don't have to ask before copying, redistribution or publishing. +** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. +***********************************************************************/ + + + +#include <stdio.h> +#include "mc.h" +#include "mc-parse.h" +#include "mc-codegen.h" +#include "mc-code.h" + +#ifdef __APPLE__ +#define USE_SSE2 +#define USE_PIC +#endif + +#if defined(__GNUC__) && __GNUC__ >= 4 + +#include "mc-include.c" + +static +char *init_src0 = "\ +#define __DBL_MIN_EXP__ (-1021) +#define __FLT_MIN__ 1.17549435e-38F +#define __DEC64_DEN__ 0.000000000000001E-383DD +#define __CHAR_BIT__ 8 +#define __WCHAR_MAX__ 2147483647 +#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 +#define __FLT_EVAL_METHOD__ 0 +#define __DBL_MIN_10_EXP__ (-307) +#define __FINITE_MATH_ONLY__ 0 +#define __DEC64_MAX_EXP__ 384 +#define __SHRT_MAX__ 32767 +#define __LDBL_MAX__ 1.18973149535723176502e+4932L +#define __APPLE_CC__ 5664 +#define __UINTMAX_TYPE__ long unsigned int +#define __DEC32_EPSILON__ 1E-6DF +#define __SCHAR_MAX__ 127 +#define __USER_LABEL_PREFIX__ _ +#define __STDC_HOSTED__ 1 +#define __DEC64_MIN_EXP__ (-383) +#define __DBL_DIG__ 15 +#define __FLT_EPSILON__ 1.19209290e-7F +#define __LDBL_MIN__ 3.36210314311209350626e-4932L +#define __DEC32_MAX__ 9.999999E96DF +#define __strong +#define __APPLE__ 1 +#define __DECIMAL_DIG__ 21 +#define __LDBL_HAS_QUIET_NAN__ 1 +#define __DYNAMIC__ 1 +#define __GNUC__ 4 +#define __MMX__ 1 +#define __FLT_HAS_DENORM__ 1 +#define __DBL_MAX__ 1.7976931348623157e+308 +#define __DBL_HAS_INFINITY__ 1 +#define __DEC32_MIN_EXP__ (-95) +#define OBJC_NEW_PROPERTIES 1 +#define __STRICT_ANSI__ 1 +#define __LDBL_HAS_DENORM__ 1 +#define __DEC32_MIN__ 1E-95DF +#define __weak __attribute__((objc_gc(weak))) +#define __DBL_MAX_EXP__ 1024 +#define __DEC128_EPSILON__ 1E-33DL +#define __SSE2_MATH__ 1 +#define __amd64 1 +#define __tune_core2__ 1 +#define __LONG_LONG_MAX__ 9223372036854775807LL +#define __GXX_ABI_VERSION 1002 +#define __FLT_MIN_EXP__ (-125) +#define __x86_64 1 +#define __DBL_MIN__ 2.2250738585072014e-308 +#define __LP64__ 1 +#define __DBL_HAS_QUIET_NAN__ 1 +#define __DEC128_MIN__ 1E-6143DL +#define __REGISTER_PREFIX__ +#define __DBL_HAS_DENORM__ 1 +#define __NO_INLINE__ 1 +#define __DEC_EVAL_METHOD__ 2 +#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL +#define __FLT_MANT_DIG__ 24 +#define __VERSION__ "4.2.1 (Apple Inc. build 5664)" +#define __DEC64_EPSILON__ 1E-15DD +#define __DEC128_MIN_EXP__ (-6143) +#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 1064 +#define __SIZE_TYPE__ long unsigned int +#define __DEC32_DEN__ 0.000001E-95DF +#define __FLT_RADIX__ 2 +#define __LDBL_EPSILON__ 1.08420217248550443401e-19L +#define __SSE_MATH__ 1 +#define __k8 1 +#define __LDBL_DIG__ 18 +#define __x86_64__ 1 +#define __FLT_HAS_QUIET_NAN__ 1 +#define __FLT_MAX_10_EXP__ 38 +#define __LONG_MAX__ 9223372036854775807L +#define __FLT_HAS_INFINITY__ 1 +#define __DEC64_MAX__ 9.999999999999999E384DD +#define __DEC64_MANT_DIG__ 16 +#define __STDC_VERSION__ 199901L +#define __DEC32_MAX_EXP__ 96 +#define __DEC128_DEN__ 0.000000000000000000000000000000001E-6143DL +#define __LITTLE_ENDIAN__ 1 +#define __LDBL_MANT_DIG__ 64 +#define __CONSTANT_CFSTRINGS__ 1 +#define __DEC32_MANT_DIG__ 7 +#define __k8__ 1 +#define __WCHAR_TYPE__ int +#define __pic__ 2 +#define __FLT_DIG__ 6 +#define __INT_MAX__ 2147483647 +#define __FLT_MAX_EXP__ 128 +#define __DBL_MANT_DIG__ 53 +#define __DEC64_MIN__ 1E-383DD +#define __WINT_TYPE__ int +#define __SSE__ 1 +#define __LDBL_MIN_EXP__ (-16381) +#define __MACH__ 1 +#define __amd64__ 1 +#define __LDBL_MAX_EXP__ 16384 +#define __SSP__ 1 +#define __LDBL_MAX_10_EXP__ 4932 +#define __DBL_EPSILON__ 2.2204460492503131e-16 +#define _LP64 1 +#define __GNUC_PATCHLEVEL__ 1 +#define __LDBL_HAS_INFINITY__ 1 +#define __GNUC_STDC_INLINE__ 1 +#define __INTMAX_MAX__ 9223372036854775807L +#define __FLT_DENORM_MIN__ 1.40129846e-45F +#define __PIC__ 2 +#define __FLT_MAX__ 3.40282347e+38F +#define __SSE2__ 1 +#define __FLT_MIN_10_EXP__ (-37) +#define __INTMAX_TYPE__ long int +#define __DEC128_MAX_EXP__ 6144 +#define __GNUC_MINOR__ 2 +#define __DBL_MAX_10_EXP__ 308 +#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L +#define __STDC__ 1 +#define __PTRDIFF_TYPE__ long int +#define __DEC128_MANT_DIG__ 34 +#define __LDBL_MIN_10_EXP__ (-4931) +#define __SSE3__ 1 +" +#ifdef __APPLE__ +"#define __APPLE__ 1\n" +"#define __GNUC__ 4\n" +"#define __BIG_ENDIAN__ 1\n" +#endif +; + +/* + + #define size_t int\n\ + +*/ + +#else + +#include "mc-include.c" + +#if defined(__GNUC__) && __GNUC__ >= 3 +static +char *init_src0 = "\ +#define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\ +#define __builtin_va_arg(ap,type) (*((type *)ap)++)\n\ +#define __builtin_va_end\n\ +#define __i386__ 1\n\ +#define __LITTLE_ENDIAN__ 1\n\ +#define __STDC__ 1\n\ +#define __extension__\n\ +// #define __restrict\n\ +#define __flexarr\n\ +#define __const const\n\ +#define __THORW\n\ +// #define __attribute__(a)\n\ +#define __inline__ inline\n\ +#define __inline inline\n\ +#define __GNUC__ 3\n\ +#define __builtin_va_list int\n\ +typedef long unsigned int __SIZE_TYPE__ ;\n\ +" + +#else +static +char *init_src0 = "\ +#define va_list int\n\ +#define va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\ +#define va_arg(ap,type) (*((type *)ap)++)\n\ +#define va_end\n\ +#define __i386__ 1\n\ +#define __LITTLE_ENDIAN__ 1\n\ +#define __STDC__ 1\n\ +#define __extension__\n\ +// #define __restrict\n\ +#define __flexarr\n\ +#define __const const\n\ +#define __THORW\n\ +// #define __attribute__(a)\n\ +#define __inline__ inline\n\ +#define __SIZE_TYPE__ long unsigned int\n\ +#define __GNUC__ 3\n\ +" + +#endif + + + ; + +#endif + +int data_alignment = 0; + +#define SIZE_OF_INT 4 +#define SIZE_OF_SHORT 2 +#define SIZE_OF_FLOAT 4 +#define SIZE_OF_DOUBLE 8 +#define SIZE_OF_LONGLONG 8 +#define ENDIAN 0 +#define ENDIAN_L 0 +#define ENDIAN_D 0 + +int eval_order = REVERSE; + +#define TEXT_EMIT_MODE 0 +#define DATA_EMIT_MODE 1 +#define RODATA_EMIT_MODE 2 + +#ifdef __APPLE__ +#else +#define DOT_SIZE 1 +#endif + +static int output_mode = TEXT_EMIT_MODE; + +static int creg; +static int ireg; +static int lreg; + +extern int lp64; + +#define regv_l(r) (r==REG_L?REG_ESI:REG_EAX) +#define regv_h(r) (r==REG_L?REG_EDI:REG_EDX) + +int code_lassop_p = 0; + +#define MAX_REGISTER 14 /* intel386のレジスタを6つまで使う*/ +#define REAL_MAX_REGISTER 16 /* intel386のレジスタが8つということ*/ +static int MAX_DATA_REG=8; +static int MAX_POINTER=8; +int MAX_REGISTER_VAR=8; +// static int MAX_FREGISTER=1; + +#define MAX_FPU_STACK 7 + +// static int MAX_INPUT_REGISTER_VAR = 0; +int MAX_CODE_INPUT_REGISTER_VAR = 6; +static int MAX_INPUT_DREGISTER_VAR = 6; +// static int MAX_INPUT_FREGISTER_VAR = 0; +static int MAX_CODE_INPUT_DREGISTER_VAR = 6; + +static int reg_sp; /* REGister Stack-Pointer */ +static int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ +static int stack_depth = 0; + +/* floating point registers */ + +static int freg_sp; /* floating point REGister Stack-Pointer */ +static int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ + +static int reg_var; + + +/* + local2 -8 + local1 <-- -6 0 local variable + %edi -12 <- disp_offset %ebp + %esi -8 + %ebx -4 + %ebp = %esp 0 + %eip 4 <- arg_offset + arg7 8 + %r9d arg6 + %r8d arg5 + %ecx arg4 + %edx arg3 + %esi arg2 + %rdi arg1 + see enter/enter1/leave see code_enter + */ +// static int arg_offset; + +static int code_disp_label; + +#ifdef __APPLE__ +static int goffset_label; +#endif + + +/* + creg current register + ireg current register for integer (int mode) + lreg current register for long long (long long mode) + + regs[] register usage + + freg current floating point register + kept in FPU stack (no register) + */ + +#define REAL_MAX_LREGISTER 2 +static int ia32regs[1+REAL_MAX_REGISTER+REAL_MAX_LREGISTER]; + + +static int *regs = ia32regs; + +static int ia32fregs[1]; +static int *fregs = ia32fregs; +static int freg; + +// register number should start 1 +// regs[] value +// 0 for not ready +// -1 use currrent register +// 1 used +// 2 (REG_VAR) register variable +// 3 pointer cache (not used in ia32) + +#define REG_EBP 1 +#define REG_ESP 2 +#define REG_EDI 3 // first argument register +#define REG_ESI 4 +#define REG_EDX 5 +#define REG_ECX 6 // for strange reason (code_assop) +#define REG_EAX 7 +#define REG_EBX 8 +#define is_int_reg(reg) 1 // (1<=reg&®<REG_EBP) + +// return value register +#define RET_FREGISTER +#define RET_DREGISTER +#define RET_LREGISTER REG_LCREG +#define RET_REGISTER REG_EAX + +// defalut current register +#define CREG_REGISTER REG_ECX +#define FREG_FREGISTER 0 + +static char *reg_name[8+1]; +static char *reg_name_l[4+1]; +static char *reg_name_w[4+1]; + +static void ascii(char *s); + +static int use_register(int virt, int real, int move); +static void shift(char *op, int reg,int creg); +static void ld_indexx(int byte, int n, int xreg,int reg,int sign); +//static void data_mode(char *name); +// static void text_mode(int align); +static int get_data_register(void); + +static void local_table(void); +static int push_struct(int e4,int t, int arg) ; +static void code_clear_stack_reg(int reg1); +#if FLOAT_CODE +static char * fload(int d); +static int code_d1(double d); +static int code_d2(double d); +static void code_save_fstacks(); +#endif +static void jcond(int l, char cond); +#if LONGLONG_CODE +static int code_l1(long long d); +static int code_l2(long long d); +#endif + +#define round16(i) align(i,16) +#define round4(i) align(i,4) + + +#define func_disp_offset (16) +#define code_disp_offset (16) + +#define arg_offset 8 +#define arg_offset1 0 +#define ARG_LVAR_OFFSET 0x10000000 + +#define code_disp_offset0 (-16) +// disp_offset +int disp_offset = code_disp_offset0; + +#define CODE_LVAR(l) ((l)+code_disp_offset0) +#define CODE_CALLER_ARG(l) ((l)+arg_offset1) +#define FUNC_LVAR(l) ((l)-func_disp_offset) +#define CALLER_ARG(l) ((l)+arg_offset1) +#define CALLEE_ARG(l) ((l)+arg_offset) +static int r1_offset_label; +static const char lpfx[] = "_"; +// static int lvar_offset_label; +static int max_func_args,max_func_arg_label; + +/* + function call stack frame + prev esp + <-------r1_offset------------------------------> + <----- ebp--> <----- esp + r+ +------------+---+---------------+----------+-------------------+ - + callee arg xx register save local caller arg + reg_save disp max_func_args*SIZE_OF_INT + lvar>0 lvar<0 lvar>0x1000 0000 + +code segment stack frame + + * gotoを呼び出した関数のr1 ! r1(goto前のr1) + disp_offset + # * ebp <---r1_offset---------> esp +r+ +----------+--+----------+----------------+-----------+----------+----+ + cousin arg xx reg save !callee arg !code local caller arg xx + r20-r29 lvar>0 lvar<0 lvar>0x1000 000 + f20-f31 <-my_func_args--><--disp-----><-max_func_arg-> + *SIZE_OF_INT *SIZE_OF_INT + + %esp should be alignment 16 + + */ + +void +code_offset_set(NMTBL *fnptr) +{ +#if 0 + int l; +#endif + int code_f = is_code(fnptr); + int lvar_offsetv = round16(-disp); + int r1_offsetv = round16(lvar_offsetv+max_func_args*SIZE_OF_INT+func_disp_offset)+8; + + if (code_f) { + printf("\t.set _%d,%d\n",code_disp_label,r1_offsetv); + } else { + // +8 makes esp alignment 16 + // printf(".set %s%d,%d\n",lpfx,lvar_offset_label,lvar_offsetv); + if (r1_offsetv-lvar_offsetv > 65000) error(-1); + // too large function arguments? + printf(".set %s%d,%d\n",lpfx,r1_offset_label,r1_offsetv); + } + if (max_func_arg_label) { + printf(".set %s%d,%d\n",lpfx,max_func_arg_label, + round16(max_func_args*SIZE_OF_INT)); + max_func_arg_label = 0; + } + +#if 0 +printf("## reg_save %d\n",reg_save); +printf("## function %s\n",fnptr->nm); + l = ARG_LVAR_OFFSET; +printf("## offset call0\t%d\n",CALLER_ARG); + l = ARG_LVAR_OFFSET+max_func_args*SIZE_OF_INT; +printf("## offset calln\t%d %d\n",CALLER_ARG,max_func_args*SIZE_OF_INT); + l = disp; +printf("## offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp); + l = 0; +printf("## offset lvar0\t%d\n",FUNC_LVAR+lvar_offsetv); + l = -reg_save; +printf("## offset regs\t%d\n",FUNC_LVAR+lvar_offsetv); +printf("## offset r1off\t%d\n",r1_offsetv); + l = 0; +printf("## offset carg0\t%d\n",CALLEE_ARG+r1_offsetv); + l = my_func_args; +printf("## offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args); +#endif +} + + +static void +lvar(int l) +{ + if (is_code(fnptr)) { + if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ + printf("%d(%%esp)",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); + } else + printf("%d(%%ebp)",CODE_LVAR(l)); + } else if (l<0) { /* local variable */ + printf("%d(%%ebp)",FUNC_LVAR(l)); + } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ + printf("%d(%%esp)",CALLER_ARG(l-ARG_LVAR_OFFSET)); + } else { /* callee's arguments */ + printf("%d(%%ebp)",CALLEE_ARG(l)); + } +} + + +#define use_int(reg) if (reg==-1) reg=use_int0() + +static int +use_int0() { + int i = creg; + if (!i||!ireg||!is_int_reg(i)) { + if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; } + if (!ireg) { + ireg = get_register(); + } + i = ireg; + } + if (!regs[i]) regs[i]=USING_REG; + creg = ireg = i; + return i; +} + +#define is_data_reg(reg) (REG_EAX<=reg&®<=REG_EDX) +#define is_pointer_reg(reg) (REG_ESI<=reg&®<=REG_EBP) + +static int +use_register(int reg0, int reg1, int move) +{ + /* + reg0 becomes reg1, if (move) copy the content. + if reg1 is used, reg0 contains old value. + */ + + char *move_op; + code_clear_stack_reg(reg1); + move_op = (regs[reg1]||regs[reg1])?"\txchg %s,%s\n":"\tmovl %s,%s\n"; + if (move && reg0!=reg1) { + printf(move_op,reg_name[reg0],reg_name[reg1]); + if (!regs[reg1]) regs[reg1]=USING_REG; + } + return reg0; +} + +#define use_data_reg(reg,keep) \ + if (reg==-1||!is_data_reg(reg)) reg=use_data_reg0(keep,reg) + +int +use_data_reg0(int keep,int reg) +{ + int ptreg =0; + int i; + if (is_pointer_reg(creg)) { + free_register(ptreg=creg); + ireg = creg = 0; + } + if (is_pointer_reg(ireg)) { + free_register(ireg); + ireg = 0; + } + i = reg==USING_REG?creg:reg; +#ifdef __APPLE__ + if (regs[i]==PTRC_REG) clear_ptr_cache_reg(i); +#endif + if (!i||!ireg||!is_data_reg(i)) { + if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; } + if (!ireg) { + ireg = get_data_register(); + } + i = ireg; + } + if (!regs[i]) regs[i]=USING_REG; + creg = ireg = i; + if (ptreg && keep) { + printf("\tmovl %s,%s\n",reg_name[ptreg],reg_name[creg]); + } + return i; +} + +static void +set_freg(int reg,int mode) +{ +} + +static void +set_ireg(int reg,int mode) +{ + if (!is_int_reg(reg)) error(-1); + if (reg!=creg) { +#ifdef __APPLE__ + if (regs[reg]==PTRC_REG) + clear_ptr_cache_reg(reg); +#endif + if (ireg && reg!=ireg ) { + if (regs[ireg]!=REG_VAR) free_register(ireg); + if (mode) { + printf("\tmovl %s,%s\n",reg_name[ireg],reg_name[reg]); + } + } + if (creg>0 && regs[creg]!=REG_VAR) free_register(creg); + if (creg==lreg) lreg = 0; + } + creg = ireg = reg; + if (!regs[reg]) regs[reg]=USING_REG; +} + +#define is_long_reg(reg) (reg==REG_LCREG||reg==REG_L) +#define use_longlong(reg) \ + if (reg==-1||is_long_reg(reg)) reg=use_longlong0(reg) + +static int +use_longlong0(int reg) +{ + int i = reg==USING_REG?creg:reg; + if (ireg) { if (regs[ireg]!=REG_VAR) free_register(ireg); ireg=0; } + if (!lreg||!regs[lreg]) { + // long long mode use all registers + code_save_stacks(); +#ifdef __APPLE__ + clear_ptr_cache(); +#endif + } + i = lreg = (reg==USE_CREG)?REG_LCREG:reg; + if (!regs[i]) regs[i]=USING_REG; + if (!regs[regv_l(i)]) regs[regv_l(i)]=USING_REG; + if (!regs[regv_h(i)]) regs[regv_h(i)]=USING_REG; + creg = lreg = i; + return i; +} + +static void +set_lreg(int reg,int mode) +{ + use_longlong(reg); +} + +char * +l_edx(int i) { + return i==REG_L?"%edi":"%edx"; +} +char * +l_eax(int i) { + return i==REG_L?"%esi":"%eax"; +} + +extern void +code_init(void) +{ + + /* called only once */ + + init_src = init_src0; + size_of_int = SIZE_OF_INT; + size_of_pointer = SIZE_OF_INT; + size_of_short = SIZE_OF_SHORT; + size_of_float = SIZE_OF_FLOAT; + size_of_double = SIZE_OF_DOUBLE; + size_of_longlong = SIZE_OF_LONGLONG; + endian = ENDIAN; + lp64 = 1; + struct_align = size_of_int; + + + // MAX_REGISTER=6; + MAX_DATA_REG=4; + MAX_POINTER=3; + MAX_REGISTER_VAR=2; + + reg_name[REG_EAX] = "%eax"; + reg_name[REG_EBX] = "%ebx"; + reg_name[REG_ECX] = "%ecx"; + reg_name[REG_EDX] = "%edx"; + reg_name[REG_ESI] = "%esi"; + reg_name[REG_EDI] = "%edi"; + reg_name[REG_EBP] = "%ebp"; + reg_name[REG_ESP] = "%esp"; + reg_name_l[REG_EAX] = "%al"; + reg_name_l[REG_EBX] = "%bl"; + reg_name_l[REG_ECX] = "%cl"; + reg_name_l[REG_EDX] = "%dl"; + reg_name_w[REG_EAX] = "%ax"; + reg_name_w[REG_EBX] = "%bx"; + reg_name_w[REG_ECX] = "%cx"; + reg_name_w[REG_EDX] = "%dx"; + +} + +extern void +emit_reinit() +{ + /* called for each file */ + output_mode = -1; +#ifdef __APPLE__ + init_ptr_cache(); +#endif +} + + +char * +register_name(int i,int byte) +{ + if (i<=0) { + error(REG_ERR); + return "%eax"; + } + if (byte==1 && i <= REG_EDX) { + return reg_name_l[i]; + } else if (byte==SIZE_OF_SHORT && i <= REG_EDX) { + return reg_name_w[i]; + } else { + return reg_name[i]; /* 0 or 4 means int */ + } +} + +void +gexpr_code_init(void){ + // use_register(creg,REG_EAX,0); + set_ireg(CREG_REGISTER,0); +} + +void +code_gexpr(int e){ + if ((is_int_reg(creg))&®s[creg]==REG_VAR) + creg = ireg = 0; + else if ((creg==REG_L)&®s[creg]==REG_VAR) + creg = lreg = 0; +} + +int +get_register(void) +{ /* 使われていないレジスタを調べる */ + int i,reg,j; + for(i=1;i<MAX_REGISTER+1;i++) { + if (! regs[i]) { /* 使われていないなら */ + regs[i]=1; /* そのレジスタを使うことを宣言し */ + return i; /* その場所を表す番号を返す */ + } + } +#ifdef __APPLE__ + /* PTR_CACHE をつぶす */ + if ((i=last_ptr_cache())) { + clear_ptr_cache_reg(i); + regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ + return i; /* その場所を表す番号を返す */ + } +#endif + /* search register stack */ + for(i=0;i<reg_sp;i++) { + if ((reg=reg_stack[i])>=0) { + code_assign_lvar( + (j=new_lvar(SIZE_OF_INT)),reg,0); + reg_stack[i]= j-REG_LVAR_OFFSET; + return reg; + } + } + error(RGERR); + return -1; /* 空いている場所がないなら、それを表す -1 を返す */ +} + +static int +get_data_register(void) +{ /* 使われていないレジスタを調べる */ + int i,reg,j; + for(i=REG_EAX;i<=REG_EDX;i++) { + if (! regs[i]) { /* 使われていないなら */ + regs[i]=1; /* そのレジスタを使うことを宣言し */ + return i; /* その場所を表す番号を返す */ + } + } +#ifdef __APPLE__ + /* PTR_CACHE をつぶす */ + while ((i=last_ptr_cache())) { + clear_ptr_cache_reg(i); + if (is_data_reg(i)) { + regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ + return i; /* その場所を表す番号を返す */ + } + } +#endif + /* search register stack */ + for(i=0;i<reg_sp;i++) { + if (is_data_reg(i) && (reg=reg_stack[i])>=0) { + code_assign_lvar( + (j=new_lvar(SIZE_OF_INT)),reg,0); + reg_stack[i]= j-REG_LVAR_OFFSET; + return reg; + } + } + error(-1); + return -1; /* 空いている場所がないなら、それを表す -1 を返す */ +} + +void +free_register(int i) { /* いらなくなったレジスタを開放 */ + if (i==REG_L) { + reg_var=0; + regs[REG_ESI]=regs[REG_EDI]=0; + } else if (regs[i]==REG_VAR) { reg_var--; + } else if(i==REG_LCREG) { //? REG_L? + regs[REG_EAX]=regs[REG_EDX]=0; + } + regs[i]=0; +} + +extern void +use_ptr_cache(int r) +{ +#ifdef __APPLE__ + regs[r]=PTRC_REG; +#else + error(-1); +#endif +} + +extern void +code_ptr_cache_def(int r,NMTBL *nptr) +{ +#ifdef __APPLE__ + char *rrn = register_name(r,0); + if (nptr->sc==STATIC && !(is_code(nptr)||is_function(nptr))) { + printf("\tleal _%s-_%d(%%ebx),%s\n",nptr->nm, + goffset_label,rrn); + } else { + printf("\tmovl L_%s$non_lazy_ptr-_%d(%%ebx),%s\n", + nptr->nm, + goffset_label,rrn); + } +#else + error(-1); +#endif +} + +/* + ESI,EDI are used as register variable + (both in integer and long long mode) + */ + +int +get_input_register_var(int i,NMTBL *nptr,int is_code) +{ + if (is_code) { + if (i>=MAX_CODE_INPUT_REGISTER_VAR) return 0; + i += REG_EDI; + regs[i]=INPUT_REG; + return list3n(REGISTER,i,nptr); + } else { + if (i>=MAX_INPUT_REGISTER_VAR) return 0; + i += REG_EDI; + regs[i]=INPUT_REG; + return list3n(REGISTER,i,nptr); + } +} + +int +get_input_dregister_var(int i,NMTBL *nptr,int is_code,int d) +{ + return 0; +} + +int +get_input_lregister_var(int i,NMTBL *nptr,int is_code) +{ + int h,l; + if (is_code) { + if (i+1>=MAX_CODE_INPUT_REGISTER_VAR) return 0; + h = REG_ESI; + l = REG_EDI; + regs[h]=regs[l]=INPUT_REG; + return list2(LREGISTER,REG_L); + } + return 0; +} + +int +get_dregister(int d) +{ + return -1; +} + +int +get_lregister_var(NMTBL *n) +{ + int h,l; + h = REG_ESI; + l = REG_EDI; + if (regs[h]==0&®s[l]==0) { + regs[h]=regs[l]=REG_VAR; regs[REG_L]=REG_VAR; + reg_var=2; + return list2(LREGISTER,REG_L); + } + return list3n(LVAR,new_lvar(SIZE_OF_LONGLONG),0); +} + +int +get_lregister() +{ + return -1; +} + + +int +register_full(void) +{ + int i; + for(i=1;i<MAX_REGISTER+1;i++) { + if (! regs[i]) { + return 0; + } + } + return 1; +} + +int +free_register_count(int d) +{ + int i,count; + count = 0; + for(i=1;i<MAX_REGISTER+1;i++) { + if (! regs[i]) count++; + } + return d?0:count; +} + +void +free_all_register(void) +{ + int i; + for(i=1;i<MAX_REGISTER+REAL_MAX_LREGISTER+1;i++) { + regs[i]=0; + } + lreg = creg = ireg = 0; + reg_var = 0; + return; +} + +extern int +code_register_overlap(int s,int t) +{ + if (car(s)==REGISTER) { + if (car(t)==REGISTER) return cadr(s)==cadr(t); + if (car(t)==LREGISTER) + return cadr(s)==REG_ESI|| cadr(s)==REG_EDI; + } else if (car(s)==LREGISTER) { + if (car(t)==LREGISTER) return 1; + if (car(t)==REGISTER) + return cadr(t)==REG_ESI|| cadr(t)==REG_EDI; + } + return 0; +} + +void +register_usage(char *s) +{ + int i; + printf("## %d: %s:",lineno,s); + if (creg) printf(" creg=%s ",register_name(creg,0)); + for(i=1;i<MAX_REGISTER+1;i++) { + printf("%d",regs[i]); + } +#if 0 + printf(" regs_stack",register_name(creg,0); + for(i=reg_sp;i>=0;i--) { + if(reg_stack[i]>=0) + printf(" %s",register_name(reg_stack[i],0)); + } +#endif + printf("## f:%d",freg_sp); + printf("\n"); +} + +void +code_arg_register(NMTBL *fnptr) +{ + int args = fnptr->dsp; + NMTBL *n; + int reg_var = 0; + int freg_var = 0; + int type; + int reg; + int offset = 0; + int is_code0 = is_code(fnptr); + + while (args) { + /* process in reverse order */ + n = ncadddr(args); + type = n->ty; + // n->dsp = offset; +// printf("### %s %d %d\n",n->nm,n->dsp,n->ty); + if (scalar(type)) { + if ((reg = get_input_register_var(reg_var,n,is_code0))) { + n->sc = REGISTER; + n->dsp = cadr(reg); + regs[n->dsp]= INPUT_REG; + reg_var++; + caddr(args)=SIZE_OF_INT; /* why we need this? */ + } + offset+=SIZE_OF_INT; + } else if (type==FLOAT||type==DOUBLE) { + if ((reg = get_input_dregister_var(freg_var,n,is_code0,1))) { + n->sc = DREGISTER; + n->dsp = cadr(reg); + fregs[n->dsp]= INPUT_REG; + freg_var++; + caddr(args)=size(type); /* why we need this? */ + } + offset+=size(type); + } else + offset+=size(type); + args = cadr(args); + } +} + +void +gexpr_init(void) +{ + text_mode(0); + if (reg_sp>0) error(-1); + if (freg_sp>0) error(-1); + reg_sp = 0; + freg_sp = 0; + stack_depth = 0; + gexpr_code_init(); + regs[creg]=1; + register_usage("gexpr_init"); +} + + +void +emit_init(void) +{ + int i; + for(i=1;i<REAL_MAX_REGISTER+1;i++) regs[i]=0; + free_all_register(); + reg_sp = 0; + freg_sp = 0; +} + +int +pop_register(void) +{ /* レジスタから値を取り出す */ + return reg_stack[--reg_sp]; +} + +void +emit_pop_free(int xreg) +{ + if (xreg>=0 && xreg!=creg && regs[xreg]!=REG_VAR) { + free_register(xreg); + } +} + + +int +get_register_var(NMTBL *nptr) +{ + int i; + for(i=REG_ESI;i<REG_EBP;i++) { + if (! regs[i]) { /* 使われていないなら */ + regs[i]=REG_VAR; /* そのレジスタを使うことを宣言し */ + return list3n(REGISTER,i,nptr); /* その場所を表す番号を返す */ + } + } + return list3n(LVAR,new_lvar(SIZE_OF_INT),0); +} + +int +get_dregister_var(NMTBL *nptr,int d) +{ + return list3n(LVAR,new_lvar(d?SIZE_OF_DOUBLE:SIZE_OF_FLOAT),0); +} + + +int +emit_push() +{ + int new_reg,old; + new_reg = get_register(); /* 絶対に取れる */ + // who free new_reg? + if (new_reg==creg) error(-1); + old = creg; + reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ + ireg = creg = new_reg; + if (!regs[creg]) regs[creg]=USING_REG; + return old; +} + +int +emit_pop(int type) +{ + int xreg,reg; + xreg=pop_register(); + if (xreg<= -REG_LVAR_OFFSET) { + reg = get_register(); + code_rlvar(REG_LVAR_OFFSET+xreg,reg); + free_lvar(REG_LVAR_OFFSET+xreg); + xreg = reg; + } + return xreg; +} + +void +code_label(int labelno) +{ +#ifdef __APPLE__ + clear_ptr_cache(); +#endif + printf("_%d:\n",labelno); +} + +void +code_gvar(int e1,int creg) { + use_int(creg); +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e1)); + if (cadr(e1)) { + printf("\tleal %d(%s),%s\n", cadr(e1),register_name(r,0), + register_name(creg,0)); + } else { + printf("\tmovl %s,%s\n", register_name(r,0), register_name(creg,0)); + } +#else + if (cadr(e1)) { + printf("\tmovl $%s+%d,%s\n",(ncaddr(e1))->nm,cadr(e1), + register_name(creg,0)); + } else { + printf("\tmovl $%s,%s\n",(ncaddr(e1))->nm,register_name(creg,0)); + } +#endif + +} + +void +code_rgvar(int e1,int creg) { + use_int(creg); +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e1)); + if (cadr(e1)) { + printf("\tmovl %d(%s),%s\n", cadr(e1),register_name(r,0), + register_name(creg,0)); + } else { + printf("\tmovl (%s),%s\n", register_name(r,0), register_name(creg,0)); + } +#else + if (cadr(e1)) { + printf("\tmovl %s+%d,%s\n",(ncaddr(e1))->nm,cadr(e1), + register_name(creg,0)); + } else + printf("\tmovl %s,%s\n",(ncaddr(e1))->nm,register_name(creg,0)); +#endif + +} + +static char * +cload(int sign,int sz) { + return sz==1?(sign?"movsbl":"movzbl"): + sz==SIZE_OF_SHORT?(sign?"movswl":"movzwl"):"movl"; +} + +void +code_crgvar(int e1,int creg,int sign,int sz){ + use_int(creg); +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e1)); + if (cadr(e1)) { + printf("\t%s %d(%s),%s\n", cload(sign,sz),cadr(e1),register_name(r,0), + register_name(creg,0)); + } else { + printf("\t%s (%s),%s\n", cload(sign,sz), + register_name(r,0), register_name(creg,0)); + } +#else + if (cadr(e1)) { + printf("\t%s %s+%d,%s\n",cload(sign,sz), + (ncaddr(e1))->nm,cadr(e1),register_name(creg,0)); + } else + printf("\t%s %s,%s\n",cload(sign,sz), + (ncaddr(e1))->nm,register_name(creg,0)); +#endif + +} + + +void +code_lvar(int e2,int creg) { + use_int(creg); + printf("\tlea "); lvar(e2); + printf(",%s\n",register_name(creg,0)); +} + + +void +code_register(int e2,int creg) { + use_int(creg); + if (e2!=creg) + printf("\tmovl %s,%s\n",register_name(e2,0),register_name(creg,0)); +} + + +void +code_rlvar(int e2,int reg) { + use_int(reg); + printf("\tmovl "); lvar(e2); + printf(",%s\n",register_name(reg,0)); +} + +extern void +code_i2c(int reg) +{ + use_data_reg(reg,1); + printf("\t%s %s,%s\n",cload(1,1), + register_name(reg,1),register_name(reg,0)); +} + +extern void +code_i2s(int reg) +{ + use_data_reg(reg,1); + printf("\t%s %s,%s\n",cload(1,SIZE_OF_SHORT), + register_name(reg,2),register_name(reg,0)); +} + +extern void +code_u2uc(int reg) +{ + use_data_reg(reg,1); + printf("\t%s %s,%s\n",cload(0,1), + register_name(reg,1),register_name(reg,0)); +} + +extern void +code_u2us(int reg) +{ + use_data_reg(reg,1); + printf("\t%s %s,%s\n",cload(0,SIZE_OF_SHORT), + register_name(reg,2),register_name(reg,0)); +} + +void +code_crlvar(int e2,int reg,int sign,int sz) { + use_int(reg); + printf("\t%s ",cload(sign,sz)); lvar(e2); + printf(",%s\n",register_name(reg,0)); + +} + + +void +code_fname(NMTBL *n,int creg) { + use_int(creg); +#ifdef __APPLE__ + if (n->sc==STATIC) { + printf("\tleal _%s-_%d(%%ebx),%s\n", n->nm, goffset_label, + register_name(creg,0)); + return; + } + int r = get_ptr_cache(n); + printf("\tmovl %s,%s\n", register_name(r,0), register_name(creg,0)); +#else + printf("\tmovl $%s,%s\n",n->nm,register_name(creg,0)); +#endif +} + +void +code_label_value(int label,int reg) { + use_int(reg); +#ifdef __APPLE__ + printf("\tleal _%d-_%d(%%ebx),%s\n", + label,goffset_label,register_name(reg,0)); +#else + printf("\tleal _%d,%s\n",label,register_name(reg,0)); +#endif +} + +void +code_const(int e2,int creg) { + use_int(creg); + printf("\tmovl $%d,%s\n",e2,register_name(creg,0)); +} + +void +code_neg(int creg) { + use_int(creg); + printf("\tnegl %s\n", register_name(creg,0)); +} + + +void +code_not(int creg) { + use_int(creg); + printf("\tnotl %s\n", register_name(creg,0)); +} + + +void +code_lnot(int creg) { + char *xrn; + + use_data_reg(creg,1); + xrn = register_name(creg,1); + printf("\tcmpl $0,%s\n", register_name(creg,0)); + printf("\tsete %s\n", xrn); + printf("\tmovzbl %s,%s\n", xrn,register_name(creg,0)); +} + +void +code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) { + char *xrn; + if (car(e2)==REGISTER) { + use_int(reg); + printf("\taddl $%d,%s\n",dir,register_name(cadr(e2),0)); + if (use) + printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(reg,0)); + return; + } + g_expr(e2); + xrn = register_name(creg,0); + use_int(reg); + printf("\t%s $%d,(%s)\n",(sz==1)?"addb":(sz==SIZE_OF_SHORT)?"addw":"addl",dir,xrn); + if (use) + printf("\t%s (%s),%s\n",cload(sign,sz),xrn,register_name(reg,0)); +} + + +void +code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) { + char *xrn; + if (car(e2)==REGISTER) { + use_int(reg); + if (use) + printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(reg,0)); + printf("\taddl $%d,%s\n",dir,register_name(cadr(e2),0)); + + return; + } + g_expr(e2); + emit_push(); + xrn = register_name((e2=emit_pop(0)),0); + use_int(reg); + if (use) + printf("\t%s (%s),%s\n",cload(sign,sz),xrn,register_name(reg,0)); + printf("\t%s $%d,(%s)\n",(sz==1)?"addb":(sz==SIZE_OF_SHORT)?"addw":"addl",dir,xrn); + emit_pop_free(e2); +} + + + +void +code_return(int creg) { + use_int(creg); + printf("\tleal _%d,%s\n",retcont,register_name(creg,0)); +} + + +void +code_environment(int creg) { + use_int(creg); + printf("\tmovl %%ebp,%s\n",register_name(creg,0)); +} + +static int rexpr_bool(int e1,int reg); +#if FLOAT_CODE +static int drexpr_bool(int e1,int reg); +#endif + +void +code_bool(int e1,int reg) { + char *xrn; + int e2,e3; + if (rexpr_bool(e1,reg)) return; +#if FLOAT_CODE + if (drexpr_bool(e1,reg)) return; +#endif + b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ + if (use) { + use_int(reg); + xrn = register_name(reg,0); + printf("\txorl %s,%s\n",xrn,xrn); + jmp(e3=fwdlabel()); + fwddef(e2); + printf("\tmovl $1,%s\n",xrn); + fwddef(e3); + } else { + fwddef(e2); + } +} + +static char * +code_gt(int cond) { + return (cond?"g":"le"); +} + +static char * +code_ugt(int cond) { + return (cond?"a":"be"); +} + +static char * +code_ge(int cond) { + return (cond?"ge":"l"); +} + +static char * +code_uge(int cond) { + return (cond?"ae":"b"); +} + +static char * +code_eq(int cond) { + return (cond?"e":"ne"); +} + +void +code_cmp_crgvar(int e1,int reg,int sz,int label,int cond) { + use_int(reg); +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e1)); + if (cadr(e1)) { + if (sz==1) + printf("\tcmpb $0,%d(%s)\n",cadr(e1),register_name(r,0)); + else if (sz==SIZE_OF_SHORT) + printf("\tcmpw $0,%d(%s)\n",cadr(e1),register_name(r,0)); + } else { + if (sz==1) + printf("\tcmpb $0,(%s)\n",register_name(r,0)); + else if (sz==SIZE_OF_SHORT) + printf("\tcmpw $0,(%s)\n",register_name(r,0)); + } +#else + if (cadr(e1)) { + if (sz==1) + printf("\tcmpb $0,%s+%d\n",(ncaddr(e1))->nm,cadr(e1)); + else if (sz==SIZE_OF_SHORT) + printf("\tcmpw $0,%s+%d\n",(ncaddr(e1))->nm,cadr(e1)); + } else { + if (sz==1) + printf("\tcmpb $0,%s\n",(ncaddr(e1))->nm); + else if (sz==SIZE_OF_SHORT) + printf("\tcmpw $0,%s\n",(ncaddr(e1))->nm); + } +#endif + jcond(label,cond); +} + + +void +code_cmp_crlvar(int e1,int reg,int sz,int label,int cond) { + use_int(reg); + if (sz==1) { + printf("\tcmpb $0,"); lvar(e1); printf("\n"); + } else if (sz==SIZE_OF_SHORT) { + printf("\tcmpw $0,"); lvar(e1); printf("\n"); + } + jcond(label,cond); +} + + +void +code_cmp_rgvar(int e1,int reg,int label,int cond) { + use_int(reg); +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e1)); + if (cadr(e1)) + printf("\tcmpl $0,%d(%s)\n",cadr(e1),register_name(r,0)); + else + printf("\tcmpl $0,(%s)\n",register_name(r,0)); +#else + if (cadr(e1)) + printf("\tcmpl $0,%s+%d\n",(ncaddr(e1))->nm,cadr(e1)); + else + printf("\tcmpl $0,%s\n",(ncaddr(e1))->nm); +#endif + jcond(label,cond); +} + + +void +code_cmp_rlvar(int e1,int reg,int label,int cond) { + use_int(reg); + printf("\tcmpl $0,"); lvar(e1); printf("\n"); + jcond(label,cond); +} + + +void +code_cmp_register(int e2,int label,int cond) { + use_int(e2); + printf("\tcmpl $0,%s\n",register_name(e2,0)); + jcond(label,cond); +} + + +void +code_string(int e1,int creg) +{ + char *s; + int lb; + NMTBL *n = ncaddr(e1); + if ((lb=attr_value(n,LABEL))) { + // already defined + return code_label_value(lb,creg) ; + } + + use_int(creg); + s=n->nm; + lb = emit_string_label(); + ascii(s); + if (output_mode==TEXT_EMIT_MODE) { + printf(".text\n"); + } else { + text_mode(0); + } +#ifdef __APPLE__ + printf("\tleal _%d-_%d(%%ebx),%s\n",lb, + goffset_label, + register_name(creg,0)); +#else + printf("\tlea _%d,%s\n",lb,register_name(creg,0)); +#endif + set_attr(n,LABEL,lb); +} + +#define MAX_COPY_LEN 20 + +/* ARG_ORDER==1 case do not allow library call in emit_copy +*/ + +void +emit_copy(int from,int to,int length,int offset,int value,int det) +{ + int dreg; + char *drn,*frn; + char *trn; + use_int(from); + use_int(to); + frn = register_name(from,0); + trn = register_name(to,0); + + /* length <0 means upward direction copy */ + switch (length) { + case 0: break; + case 1: case -1: + drn = register_name(dreg = get_data_register(),1); + printf("\tmovb %d(%s),%s\n",offset,frn,drn); + printf("\tmovb %s,%d(%s)\n",drn,offset,trn); + free_register(dreg); + break; + case 2: case -2: + drn = register_name(dreg = get_data_register(),2); + printf("\tmovw %d(%s),%s\n",offset,frn,drn); + printf("\tmovw %s,%d(%s)\n",drn,offset,trn); + free_register(dreg); + break; + case 4: case -4: + drn = register_name(dreg = get_register(),0); + printf("\tmovl %d(%s),%s\n",offset,frn,drn); + printf("\tmovl %s,%d(%s)\n",drn,offset,trn); + free_register(dreg); + break; + default: + if (length <0) { + if (length > -MAX_COPY_LEN) { + for(;length<=-4;length+=4,offset-=4) + emit_copy(from,to,-4,offset-4,0,det); + for(;length<=-2;length+=2,offset-=2) + emit_copy(from,to,-2,offset-2,0,det); + if(length<0) + emit_copy(from,to,length,offset-1,0,det); + break; + } + } else if (length <=MAX_COPY_LEN) { + for(;length>=4;length-=4,offset+=4) + emit_copy(from,to,4,offset,0,det); + for(;length>=2;length-=2,offset+=2) + emit_copy(from,to,2,offset,0,det); + if(length>0) + emit_copy(from,to,length,offset,0,det); + break; + } + // should be parallel_rassign.... + // clear_ptr_cache(); + // code_save_stacks(); + + printf("\tpushl %%esi\n"); + printf("\tpushl %%edi\n"); + printf("\tpushl %%ecx\n"); + printf("\tpushl %s\n",register_name(from,0)); + printf("\tpushl %s\n",register_name(to,0)); + printf("\tpopl %%edi\n"); + printf("\tpopl %%esi\n"); + if (length<0) { + printf("\tmovl $%d,%%ecx\n",-length/4); + printf("\taddl $%d,%%esi\n",-length-4); + printf("\taddl $%d,%%edi\n",-length-4 + +(to==REG_ESP?4*4:0) + ); + printf("\tstd\n\trep\n\tmovsl\n"); + printf("\tpopl %%ecx\n"); + printf("\tpopl %%edi\n"); + printf("\tpopl %%esi\n"); + if(length%4) { + offset = offset+length/SIZE_OF_INT; + length=length%4; + emit_copy(from,to,length,offset,0,det); + } + } else { + printf("\tmovl $%d,%%ecx\n",length/4); + if (to==REG_ESP) + printf("\taddl $%d,%%edi\n",4*4); + printf("\tcld\n\trep\n\tmovsl\n"); + printf("\tpopl %%ecx\n"); + printf("\tpopl %%edi\n"); + printf("\tpopl %%esi\n"); + if(length%4) { + offset = offset+length/SIZE_OF_INT; + length=length%4; + emit_copy(from,to,length,offset,0,det); + } + } + } + if (value) { + /* creg must point top of the destination data */ + /* this code is necessary for the value of assignment or function call */ + /* otherwise we don't need this */ + if(creg!=to) { + if (regs[creg]!=REG_VAR) free_register(creg); creg=to; + } + } +} + +static int +push_struct(int e4,int t, int arg) +{ + int length,dreg; + g_expr(e4); + length=size(t); + if(length%SIZE_OF_INT) { + length += SIZE_OF_INT - (length%SIZE_OF_INT); + } + emit_push(); + code_lvar(cadr(arg),USE_CREG); + dreg = emit_pop(0); + + // copy dreg to creg with length + // try small amount copy + /* downward direction copy */ + emit_copy(dreg,creg,length,0,0,1); + emit_pop_free(dreg); + /* we have value in creg, it may be changed */ + return length/SIZE_OF_INT; +} + +static int +simple_arg(int e3) +{ + return !contains_p(e3,not_simple_p); +} + +#define caller_arg_offset_v(arg) (ARG_LVAR_OFFSET+(arg)*SIZE_OF_INT) + +/* + Eary implementation uses pushl arg for function call. gcc + use the same arguement evaluation order. Of course, the + order is unspecified in C language, but it is better to + use same argument evaluation order. Especially for test + program. + */ +#define ARG_ORDER 1 +#if (ARG_ORDER==1) + +static int delayed_arg; + +#endif + +static int +compute_complex_arg(int e3,int reg_arg_list,int arg) { + int t=caddr(e3); + int e4 = car(e3); + reg_arg_list = list2(arg,reg_arg_list); +#if ARG_ORDER==1 + delayed_arg = list2(assign_expr0(arg,e4,t,t),delayed_arg); +#else + g_expr_u(assign_expr0(arg,e4,t,t)); +#endif + + + + car(e3) = arg; + return reg_arg_list; +} + + +static void +increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) { + int nargs=0,reg_arg=0,freg_arg=0; + int t=caddr(e3); + if(scalar(t)) { + nargs ++ ; reg_arg++; freg_arg++; + } else if (t==LONGLONG||t==ULONGLONG||t==DOUBLE) { + nargs ++ ; reg_arg++; + nargs ++ ; reg_arg++; + } else if (t==FLOAT) { + reg_arg ++ ; freg_arg++; + nargs += size(t)/SIZE_OF_INT; + } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { + nargs += round4(size(t))/SIZE_OF_INT; + } else { + error(TYERR); + nargs ++ ; + } + *pnargs += nargs; + *preg_arg += reg_arg; + *pfreg_arg += freg_arg; +} + +#define AS_SAVE 1 +#define AS_ARG 0 + +static int +get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) +{ + if(scalar(t)) { + if (mode==AS_SAVE) { + if (parse_mode) + return get_register_var(0); + return list3n(LVAR,new_lvar(size(t)),0); + } else + return list3n(LVAR,caller_arg_offset_v(nargs),0); + } else if (t==LONGLONG||t==ULONGLONG) { + if (mode==AS_SAVE) { + if (parse_mode) + return get_lregister_var(0); + return list3n(LVAR,new_lvar(size(t)),0); + } else + return list3n(LVAR,caller_arg_offset_v(nargs),0); + } else if (t==FLOAT) { + if (mode==AS_SAVE) { + if (parse_mode) + return get_dregister_var(0,0); + return list3n(LVAR,new_lvar(size(t)),0); + } else + return list3n(LVAR,caller_arg_offset_v(nargs),0); + } else if (t==DOUBLE) { + if (mode==AS_SAVE) { + if (parse_mode) + return get_dregister_var(0,1); + return list3n(LVAR,new_lvar(size(t)),0); + } else + return list3n(LVAR,caller_arg_offset_v(nargs),0); + } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { + if (mode==AS_SAVE) { + if (parse_mode) + return get_register_var(0); + return list3n(LVAR,new_lvar(size(t)),0); + } else + return list3n(LVAR,caller_arg_offset_v(nargs),0); + } else { + error(-1); + if (parse_mode) + return get_register_var(0); + return list3n(LVAR,new_lvar(size(t)),0); + } +} + +static void +code_call(int e2,NMTBL *fn,int jmp) +{ + if (car(e2) == FNAME) { +#ifdef __APPLE__ + printf("\tcall\tL_%s$stub\n",fn->nm); +#else + printf("\tcall\t%s\n",fn->nm); +#endif + } else { + printf("\tcall\t*%s\n",register_name(REG_EAX,0)); + } +} + +int +function(int e1) +{ + + int e2,e3,e4,e5,nargs,t; + int arg,reg_arg,freg_arg,arg_assign; + int dots; + int reg_arg_list=0,ret_type,special_lvar; + NMTBL *fn = 0; + int jmp = 0; + int complex_; + int pnargs,preg_arg,pfreg_arg; + int stargs; + int half_register = 0; +#if (ARG_ORDER==1) + int save_delayed_arg = delayed_arg; + int as_save = AS_ARG; // 1st pushed argment will evaluate at the last + delayed_arg = 0; +#else + const int as_save = AS_SAVE; +#endif + + special_lvar = -1; + ret_type = function_type(cadddr(e1),&dots); + if (caddr(cadddr(e1))==0) dots=1; + + arg_assign = 0; + e2 = cadr(e1); + if (car(e2) == FNAME) { + fn=ncaddr(e2); + } else { + if (car(e2)==INDIRECT) e2=cadr(e2); // (*func)(i) case + jmp = list3(REGISTER,REG_EAX,0); + + if (!simple_arg(e2)) { + e3=get_register_var(0); + reg_arg_list = list2(e3,reg_arg_list); + g_expr_u(assign_expr0(e3,e2,INT,INT)); + e2=e3; + } + arg_assign = list2(assign_expr0(jmp,e2,INT,INT),arg_assign); + } + /* First we execute complex argument to avoid interaction with + input variables. Remain the last complex argument in complex_. */ + stargs = 0; + complex_ = 0; + nargs = reg_arg = freg_arg = 0; + pnargs = preg_arg = pfreg_arg = 0; + for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { + t=caddr(e3); + if (reg_arg==3 && (t==DOUBLE||t==LONGLONG||t==ULONGLONG)) { + half_register=1; + } + if ((e5= !simple_arg(car(e3)))) { + if (complex_) { + arg = get_input_arg(caddr(complex_),as_save, + pnargs,preg_arg,pfreg_arg); +#if ARG_ORDER==1 + as_save = AS_SAVE; +#endif + reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); + } + // memorise last complex arg parameter + pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg; + complex_ = e3; + } + if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { + // The struct should be pushed after complex arguments. + if (e5) { // compute address only, complex_ is me now. Clear it. + complex_ = 0; + e4 = car(e3); + if (car(e4)==RSTRUCT) e4 = cadr(e4); + if (!simple_arg(e4)) { + // Calculate complex struct address here. + // If simple, leave it. + arg = get_register_var(0); +#if ARG_ORDER==1 + delayed_arg = list2( + assign_expr0(arg,e4,INT,INT), + delayed_arg); +#else + g_expr_u(assign_expr0(arg,e4,INT,INT)); +#endif + car(e3)=arg; + reg_arg_list = list2(arg,reg_arg_list); + + car(e3) = rvalue_t(arg,INT); + } + } + stargs = list4(e3,stargs,nargs,reg_arg); + } + increment_function_arg(e3,&nargs,®_arg,&freg_arg); + } +#if (ARG_ORDER==1) + if (complex_) { + arg = get_input_arg(caddr(complex_),as_save, + pnargs,preg_arg,pfreg_arg); + reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); + } + for(;delayed_arg;delayed_arg = cadr(delayed_arg)) { + g_expr_u(car(delayed_arg)); + } +#endif + + /* now all input register vars are free */ + code_save_stacks(); + + // set_lreg(LREG_LREGISTER,0); + set_freg(FREG_FREGISTER,0); + set_ireg(CREG_REGISTER,0); + + // Struct arguments need emit_copy. it destructs 3 input registers. + // But it returns no value on a register. So calculate it here. + // We cannot do this in the previous loop, because the copied struct may be + // override by other complex arguments. But before this we have to check + // complex_. + + // ARG_ORDER==1 case put the last value on the top of stack. + // emit_copy/push_struct must preserve argument stack, i.e. + // no library call is allowed. + + if (stargs) { +#if (ARG_ORDER!=1) + if (complex_) { + arg = get_input_arg(caddr(complex_),AS_SAVE, + pnargs,preg_arg,pfreg_arg); + reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); + } +#endif + for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) { + e3 = car(stargs); + e4 = car(e3); + t = caddr(e3); + arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0); + push_struct(e4,t,arg); + car(e3)=0; // done + + + } +#if (ARG_ORDER!=1) + } else { + // last complex argument can use input register + if (complex_) { + arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg) +; + reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); + + car(complex_) = 0; // done. + + + } +#endif + } + + nargs = reg_arg = freg_arg = 0; + // calc stack arguments first, it may requires extra registers, + // and we can still use input registers now. + for (e3 = e1; e3; + increment_function_arg(e3,&nargs,®_arg,&freg_arg), + e3 = cadr(e3)) { + if (!(e4=car(e3))) continue; + t=caddr(e3); + arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg); + if (car(arg)!=LVAR) continue; + g_expr_u(assign_expr0(arg,e4,t,t)); + car(e3)=0; // done + } + if (max_func_args<nargs) max_func_args=nargs; + for(;arg_assign;arg_assign=cadr(arg_assign)) { + g_expr_u(car(arg_assign)); + } + clear_ptr_cache(); + code_call(e2,fn,jmp); + free_register_var(reg_arg_list); + if (ret_type==DOUBLE||ret_type==FLOAT) { + } else if (ret_type==LONGLONG||ret_type==ULONGLONG) { + use_longlong0(USE_CREG); + } else if (ret_type==VOID) { + } else { + if (use) + set_ireg(RET_REGISTER,0); + else + set_ireg(CREG_REGISTER,0); + } +#if (ARG_ORDER==1) + delayed_arg = save_delayed_arg; +#endif + return ret_type; +} + +void +code_alloca(int e1,int reg) +{ + char *crn; + + if (!is_const(e1)) { + g_expr(list3(BAND,list3(ADD,e1,list2(CONST,15)),list2(CONST,~15))); + use_int(reg); + } else { + use_int(reg); + code_const(round16(cadr(e1)),reg); + } + crn = register_name(reg,0); + printf("\tsubl\t%s, %%esp\n",crn); + if (!max_func_arg_label) max_func_arg_label = fwdlabel(); + printf("\tmovl $%s%d,%s\n",lpfx,max_func_arg_label ,crn); + printf("\tadd\t%%esp, %s\n",crn); +} + +void +code_frame_pointer(int e3) { + use_int(e3); + printf("\tmovl %s,%%ebp\n",register_name(e3,0)); +} + +int +code_frame_pointer_register() +{ + return list2(REGISTER,REG_fp); +} + +void +code_fix_frame_pointer(int disp_offset) { + // must be empty +} + +void +code_jmp(char *s) { +#ifdef __APPLE__ + printf("\tjmp\tL_%s$stub\n",s); +#else + printf("\tjmp %s\n",s); +#endif +} + + +void +code_indirect_jmp(int e2) { + use_int(e2); + printf("\tjmp *%s\n",register_name(e2,0)); +} + +void +code_rindirect(int e1, int reg,int offset, int sign,int byte) +{ + char *crn,*op; + g_expr(e1); + op=cload(sign,byte); + crn = register_name(creg,0); + use_int(reg); + printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0)); +} + +#if FLOAT_CODE +int +code_drindirect(int e1, int reg,int offset, int d) +{ + g_expr(e1); + printf("\t%s %d(%s)\n",fload(d),offset,register_name(creg,0)); + return DOUBLE; +} +#endif + +#if LONGLONG_CODE + +static void +lload(int creg,int offset,int reg) +{ + char *crn = register_name(creg,0); + use_longlong(reg); + if((reg==REG_L&&creg==REG_ESI)||(creg==REG_EAX)) { + printf("\tmovl %d(%s),%s\n",offset+SIZE_OF_INT,crn,l_edx(reg)); + printf("\tmovl %d(%s),%s\n",offset,crn,l_eax(reg)); + } else { + printf("\tmovl %d(%s),%s\n",offset,crn,l_eax(reg)); + printf("\tmovl %d(%s),%s\n",offset+SIZE_OF_INT,crn,l_edx(reg)); + } +} + +int +code_lrindirect(int e1, int reg, int offset, int us) +{ + int reg0; + g_expr(e1); + reg0=creg; + use_longlong(reg); + lload(reg0,offset,reg); + return LONGLONG; +} +#endif + +char * +move(int byte) +{ + return byte==1?"movb":byte==SIZE_OF_SHORT?"movw":"movl"; +} + +void +code_assign_gvar(int e2,int creg,int byte) { + if (byte) { use_data_reg(creg,1); + } else { use_int(creg); } +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e2)); + if (cadr(e2)) + printf("\t%s %s,%d(%s)\n",move(byte),register_name(creg,byte), + cadr(e2),register_name(r,0)); + else + printf("\t%s %s,(%s)\n",move(byte),register_name(creg,byte), + register_name(r,0)); +#else + if (cadr(e2)) + printf("\t%s %s,%s+%d\n",move(byte),register_name(creg,byte),(ncaddr(e2))->nm,cadr(e2)); + else + printf("\t%s %s,%s\n",move(byte),register_name(creg,byte),(ncaddr(e2))->nm); +#endif +} + +void +code_assign_lvar(int e2,int creg,int byte) { + if (byte) { use_data_reg(creg,1); + } else { use_int(creg); } + printf("\t%s %s,",move(byte),register_name(creg,byte)); + lvar(e2); printf("\n"); +} + +void +code_assign_register(int e2,int byte,int creg) { + use_int(creg); + if (creg!=e2) + printf("\tmovl %s,%s\n",register_name(creg,0),register_name(e2,0)); +} + +void +code_assign(int e2,int byte,int creg) { + use_int(e2); + if (byte) { use_data_reg(creg,1); + } else { use_int(creg); } + printf("\t%s %s,(%s)\n",move(byte),register_name(creg,byte),register_name(e2,0)); +} + +void +code_register_assop(int e2,int reg, int op,int byte) { + // reg <= reg(e2) op=reg + use_int(reg); + tosop(op,e2,reg); +} + +void +code_assop(int op,int creg,int byte,int sign) { + int xreg; + // (*pop()) op = creg + // creg should be ecx + + use_int(creg); + xreg = emit_pop(0); /* pop e3 value */ + emit_push(); + ld_indexx(byte,0,creg,ireg,sign); + tosop(op,ireg,xreg); + emit_pop_free(xreg); + if (byte) { + use_data_reg(ireg,1); + } + xreg = emit_pop(0); /* pop e3 value */ + printf("\t%s %s,(%s)\n",move(byte),register_name(ireg,byte),register_name(xreg,0)); + emit_pop_free(xreg); +} + +int +tosop_operand_safe_p(int op) +{ + switch(op) { + case ADD: case SUB: case CMP: + case BAND: case EOR: case BOR: + case MUL: case UMUL: + return 1; + default: return 0; + } +} + +void +tosop(int op,int reg,int oreg) +{ + int ox=0; + char *orn,*crn; + // creg = creg op oreg + + use_int(reg); + + if(oreg==-1) { + error(-1); + } else if (oreg<= -REG_LVAR_OFFSET) { + ox = get_register(); if (ox<0) error(-1); + code_rlvar(oreg+REG_LVAR_OFFSET,ox); + free_lvar(oreg+REG_LVAR_OFFSET); + oreg = ox; + } + + switch(op) { + case LSHIFT: + case ULSHIFT: + shift("sall",oreg,reg); + if(ox) free_register(ox); + return; + case RSHIFT: + shift("sarl",oreg,reg); + if(ox) free_register(ox); + return; + case URSHIFT: + shift("shrl",oreg,reg); + if(ox) free_register(ox); + return; + } + // regs[oreg]=1; + orn = register_name(oreg,0); + crn = register_name(reg,0); + switch(op) { + case ADD: + printf("\taddl %s,%s\n",orn,crn); + break; + case SUB: + printf("\tsubl %s,%s\n",orn,crn); + break; + case CMP: + printf("\tcmpl %s,%s\n",orn,crn); + break; + case BAND: + printf("\tandl %s,%s\n",orn,crn); + break; + case EOR: + printf("\txorl %s,%s\n",orn,crn); + break; + case BOR: + printf("\torl %s,%s\n",orn,crn); + break; + case MUL: + case UMUL: + printf("\t%s %s,%s\n","imull",orn,crn); + break; + case DIV: + case UDIV: + case MOD: + case UMOD: +#ifdef __APPLE__ + if (regs[REG_EDX]==PTRC_REG) + clear_ptr_cache_reg(REG_EDX); +#endif + use_register(reg,REG_EAX,1); + if (oreg==REG_EAX) oreg=reg; + if (oreg==REG_EDX) { + use_register(oreg,REG_ECX,1); + oreg = REG_ECX; + } + orn = register_name(oreg,0); + printf((op==DIV||op==MOD)? + "\tcltd\n\tidivl %s\n": + "\txor %%edx,%%edx\n\tdivl %s\n",orn); + set_ireg((op==MOD||op==UMOD)?REG_EDX:REG_EAX,0); + set_ireg(reg,1); + break; + } + if(ox && ox!=ireg) free_register(ox); +} + +int +code_const_op_p(int op,int e) +{ + if (car(e)!=CONST) return 0; + if (op==DIV||op==UDIV) return ilog(cadr(e)); + if (op==MOD||op==UMOD) return 0; + else return 1; +} + +void +oprtc(int op,int reg,int orn) +{ + char *crn; + int datareg; + use_int(reg); + crn = register_name(reg,0); + orn = cadr(orn); + datareg=is_data_reg(reg); + + switch(op) { + case LSHIFT: + case ULSHIFT: + printf("\tsall $%d,%s\n",orn,crn); + return; + case DIV: + orn = ilog(orn); + case RSHIFT: + printf("\tsarl $%d,%s\n",orn,crn); + return; + case UDIV: + orn = ilog(orn); + case URSHIFT: + printf("\tshrl $%d,%s\n",orn,crn); + return; + case ADD: + printf("\taddl $%d,%s\n",orn,crn); + break; + case SUB: case CMP: + printf("\tsubl $%d,%s\n",orn,crn); + break; + case BAND: + if (datareg&&(orn & ~255)==~255) + printf("\tandb $%d,%s\n",orn,register_name(reg,1)); + else if (datareg&&(orn & ~65535)==~65535) + printf("\tandw $%d,%s\n",orn,register_name(reg,2)); + else + printf("\tandl $%d,%s\n",orn,crn); + break; + case EOR: + printf("\txorl $%d,%s\n",orn,crn); + break; + case BOR: + if (datareg&&(orn & ~255)==0) + printf("\tor $%d,%s\n",orn,register_name(reg,1)); + else if (datareg&&(orn & ~65535)==0) + printf("\tor $%d,%s\n",orn,register_name(reg,2)); + else + printf("\torl $%d,%s\n",orn,crn); + break; + case MUL: + case UMUL: + if (ilog(orn)) { + printf("\tsall $%d,%s\n",ilog(orn),crn); + } else + printf("\t%s $%d,%s\n","imull",orn,crn); + break; + default: + error(-1); + } +} + + +void +shift(char *op, int oreg,int reg) +{ + int dreg; + use_register(oreg,REG_ECX,1); + dreg = (reg==REG_ECX)?oreg:reg; + printf("\t%s %%cl,%s\n",op,register_name(dreg,0)); + set_ireg(dreg,0); + set_ireg(reg,1); +} + +void +ld_indexx(int byte, int n, int xreg,int reg,int sign) +{ + if (byte) { + use_data_reg(reg,1); + } else { + use_int(reg); + } + if (n) + printf("\t%s %d(%s),%s\n",cload(sign,byte),n, + register_name(xreg,0),register_name(reg,0)); + else + printf("\t%s (%s),%s\n",cload(sign,byte), + register_name(xreg,0),register_name(reg,0)); +} + +int +code_csvalue() +{ + return glist2(REGISTER,creg); /* for switch value */ +} + +void +code_cmpdimm(int e, int csreg,int label,int cond) +{ + /* used in dosiwtch() */ + set_ireg(csreg,0); + printf("\tcmpl $%d,%s\n",e,register_name(creg,0)); + jcond(label,cond); +} + +void +code_opening(char *filename) +{ + printf("\t.file \"%s\"\n",filename); + printf("\t.version\t\"01.01\"\n"); + /* printf("gcc2_compiled.:\n"); */ + // printf(".text\n"); +} + +void +code_closing() +{ + global_table(); + printf("\t.ident \"Micro-C compiled\"\n"); +} + +static char * +code_cond(int op,int cond) +{ + switch(op) { + case GT: return code_gt(cond); + case UGT: return code_ugt(cond); + case GE: return code_ge(cond); + case UGE: return code_uge(cond); + case LT: return code_ge(!cond); + case ULT: return code_uge(!cond); + case LE: return code_gt(!cond); + case ULE: return code_ugt(!cond); + case EQ: return code_eq(cond); + case NEQ: return code_eq(!cond); + default: return 0; + } +} + +static int +rexpr_bool(int e1,int reg) +{ + char *s; + if (!(s=code_cond(car(e1),1))) return 0; + g_expr(list3(CMP,cadr(e1),caddr(e1))); + use_data_reg(reg,1); + printf("\tset%s\t%s\n",s,register_name(reg,1)); + printf("\tmovzbl %s,%s\n",register_name(reg,1),register_name(reg,0)); + return 1; +} + +int +rexpr(int e1, int l1, int cond,int t) +{ + g_expr(list3(CMP,cadr(e1),caddr(e1))); + printf("\tj%s\t_%d\n",code_cond(car(e1),cond),l1); + return l1; +} + + +static void +jcond(int l, char cond) +{ + printf("\tj%s\t_%d\n",cond==LT?code_ge(0):cond?"ne":"e",l); +} + +void +jmp(int l) +{ + printf("\tjmp\t_%d\n",l); + control = 0; + /* align? */ + /* + this is not allowed because of ? operator + use_register(creg,REG_EAX,0); + */ +} + +void +code_comment(char *s) +{ + printf("## %s",s); +} + + +void +code_enter(char *name) +{ + text_mode(0); + printf("\t.align 4\n"); +#ifndef __APPLE__ + if (stmode!=STATIC) + printf(".globl %s\n",name); + printf("\t.type\t%s,@function\n",name); + printf("%s:\n",name); +#else + if (stmode!=STATIC) + printf(".globl _%s\n",name); + printf("_%s:\n",name); + clear_ptr_cache(); +#endif +} + + +void +code_enter1(int args) +{ + code_disp_label=fwdlabel(); + printf("\tlea -_%d(%%ebp),%%esp\n",code_disp_label); + + // printf("## args %d disp %d code_disp_offset=%d\n",args,disp,code_disp_offset); +#ifdef __APPLE__ + printf("\tcall\t___i686.get_pc_thunk.bx\n"); + printf("_%d:\n",labelno); + goffset_label = labelno; + labelno++; + regs[REG_EBX] = 1; +#endif +} + +void +code_leave(char *name) +{ + code_offset_set(fnptr); +#ifndef __APPLE__ + printf("_%d:\n",labelno); + printf("\t.size\t%s,_%d-%s\n",name,labelno,name); + local_table(); + labelno++; +#else + local_table(); +#endif + free_all_register(); +} + +void +enter(char *name) +{ + text_mode(0); + printf("\t.align 2\n"); +#ifndef __APPLE__ + if (stmode!=STATIC) + printf(".globl %s\n",name); + printf("%s:\n",name); + printf("\t.type\t%s,@function\n",name); +#else + if (stmode!=STATIC) + printf(".globl _%s\n",name); + printf("_%s:\n",name); +#endif + +// lvar_offset_label = fwdlabel(); + r1_offset_label = fwdlabel(); + max_func_args = 0; + + printf("\tpushl %%ebp\n"); + printf("\tmovl %%esp,%%ebp\n"); + printf("\tpushl %%ebx\n"); + printf("\tpushl %%esi\n"); + printf("\tpushl %%edi\n"); + printf("\tlea -%s%d(%%ebp),%%esp\n",lpfx,r1_offset_label); +#ifdef __APPLE__ + printf("\tcall\t___i686.get_pc_thunk.bx\n"); + printf("_%d:\n",labelno); + goffset_label = labelno; + labelno++; + regs[REG_EBX] = 1; + clear_ptr_cache(); +#endif + + control=1; +} + +void +enter1() +{ + text_mode(0); +} + +void +code_label_call(int l) +{ + printf("\tcall\tL_%d\n",l); +} + +void +code_ret() +{ + printf("\tret\n"); + control=0; +} + +static void +make_return_continuation() +{ + int ty = cadr(fnptr->ty); + fwddef(retcont); + if (ty==FLOAT||ty==DOUBLE) { + printf("\tfldl %d(%%ebp)\n",-SIZE_OF_DOUBLE); + printf("\tmovl %s,%%ebp\n",reg_name[REG_ESI]); + } else if (ty==LONGLONG||ty==ULONGLONG) { + set_lreg(RET_LREGISTER,0); + printf("\tmovl %d(%%ebp),%%ebp\n",disp-SIZE_OF_INT); + } else if (ty>0&&( car(ty)==STRUCT || car(ty)==UNION)) { + set_ireg(RET_REGISTER,0); + printf("\tmovl %d(%%ebp),%s\n",disp-SIZE_OF_INT, + register_name(creg,0)); + printf("\tmovl %s,%%ebp\n",reg_name[REG_EDI]); + } else if (ty!=VOID) { + set_ireg(RET_REGISTER,0); + printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg,0)); + printf("\tmovl %s,%%ebp\n",reg_name[REG_EDI]); + } +} + +void +leave(int control, char *name) +{ + +#ifdef __APPLE__ + disp &= -(SIZE_OF_INT*4); // 16byte alignment + disp -= 12; +#else + disp &= -SIZE_OF_INT; +#endif + if (control) + code_set_return_register(1); + if (retcont) { + if (control) + jmp(retlabel); + make_return_continuation(); + } + fwddef(retlabel); + code_offset_set(fnptr); + + printf("\tlea %d(%%ebp),%%esp\n",-12); + printf("\tpopl %%edi\n"); + printf("\tpopl %%esi\n"); + printf("\tpopl %%ebx\n"); + printf("\tleave\n"); + printf("\tret\n"); +#ifndef __APPLE__ + printf("_%d:\n",labelno); + printf("\t.size\t%s,_%d-%s\n",name,labelno,name); +#endif + local_table(); + labelno++; + free_all_register(); +} + +int +code_get_fixed_creg(int reg,int type) { + if (type==FLOAT||type==DOUBLE) { + return 0; + } else if (type==LONGLONG||type==ULONGLONG) { + use_longlong(reg); + return reg; + } else { + if (reg==USE_CREG) { + if (regs[CREG_REGISTER]==0) { + set_ireg(CREG_REGISTER,is_int_reg(creg)&®s[creg]==USING_REG); + return CREG_REGISTER; + } + } + use_int(reg); + return reg; + } +} + +void +code_set_fixed_creg(int reg,int mode,int type) { + if (type==FLOAT||type==DOUBLE) { + } else if (type==LONGLONG||type==ULONGLONG) { + } else { + set_ireg(reg,mode); + } +} + +int +code_set_return_register(int mode) { + // before goto leave code, set return register + if (cadr(fnptr->ty)==FLOAT) { + // set_freg(RET_FREGISTER,mode); + return 0; + } else if (cadr(fnptr->ty)==DOUBLE) { + // set_dreg(RET_DREGISTER,mode); + return 0; + } else if (cadr(fnptr->ty)==LONGLONG||cadr(fnptr->ty)==ULONGLONG) { + set_lreg(RET_LREGISTER,mode); + return ireg; + } else if (cadr(fnptr->ty)==VOID) { + return 0; + } else { + set_ireg(RET_REGISTER,mode); + return ireg; + } +} + +void +gen_gdecl(char *n, int gpc) +{ + // must be empty +} + +extern void +ascii(char *s) +{ +#ifdef __APPLE__ + printf("\t.ascii \""); +#else + printf("\t.string \""); +#endif + while(*s) { + if (*s=='\n') + printf("%cn",92); + else if (*s<' ') + printf("%c%03o",92,*s); + else if (*s=='\\') + printf("\\\\"); + else if (*s==34) + printf("%c%c",92,34); + else + printf("%c",*s); + s++; + } +#ifdef __APPLE__ + printf("\\0%c\n",34); +#else + printf("%c\n",34); +#endif +} + +extern int +emit_string_label() +{ + int lb; + cstring_mode(); + lb=fwdlabel(); + printf("_%d:\n",lb); + return lb; +} + +extern void +emit_string(char *s,int t) +{ + t = type_value(t); + if (car(t)==ARRAY && + (type_value(cadr(t))==CHAR||type_value(cadr(t))==UCHAR)) { + ascii(s); + } else { + int l = emit_string_label(); + ascii(s); + emit_label(l); + } + return; +} + +void +code_align(int t) +{ + int d; + switch(t) { + case CHAR: case UCHAR: return; + case SHORT: case USHORT: d = data_alignment & 1; break; + default: d = data_alignment & 3; + } + if (d) { + printf("\t.align 2\n"); + data_alignment = 0; + } +} + +extern void +emit_global(NMTBL *n,int a,int e) +{ + int t = type_value(n->ty); + if (e>0 && car(e)==STRING && t>0 && car(t)==ARRAY && + (type_value(cadr(t))==CHAR||type_value(cadr(t))==UCHAR)) { + cstring_mode(); + } else + data_mode(n->nm); + code_align(a); +#ifdef __APPLE__ + if (n && n->sc!=STATIC) + printf(".globl\t_%s\n",n->nm); + printf("_%s:\n",n->nm); +#else + if (n && n->sc!=STATIC) + printf(".globl\t%s\n",n->nm); + printf("%s:\n",n->nm); +#endif +} + +extern void +emit_space(int sp) +{ + data_mode(0); + printf("\t.space\t%d\n",sp); +} + +extern void +emit_char(int d) +{ + data_mode(0); + printf("\t.byte %d\n",d); +} + +extern void +emit_short(int d) +{ + data_mode(0); + printf("\t.short %d\n",d); +} + +extern void +emit_int(int d) +{ + data_mode(0); + printf("\t.long %d\n",d); +} + +extern void +emit_longlong(int e) +{ +#if LONGLONG_CODE + long long ll = lcadr(e); + data_mode(0); +#if (ENDIAN_L==0) + printf("\t.long\t0x%x,0x%x\n",code_l1(ll),code_l2(ll)); +#else + printf("\t.long\t0x%x,0x%x\n",code_l2(ll),code_l1(ll)); +#endif +#endif +} + +extern void +emit_double(int e) +{ +#if FLOAT_CODE + double d = dcadr(e); + data_mode(0); +#if (ENDIAN_D==0) + printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d)); +#else + printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d)); +#endif +#endif +} + +extern void +emit_float(int e) +{ +#if FLOAT_CODE + float f = dcadr(e); + data_mode(0); + printf("\t.long\t0x%x\n",*(int *)&f); +#endif +} + +extern void +emit_address(char *s,int offset) +{ + data_mode(0); +#ifdef __APPLE__ + if (offset) + printf("\t.long _%s+%d\n",s,offset); + else + printf("\t.long _%s\n",s); +#else + if (offset) + printf("\t.long %s+%d\n",s,offset); + else + printf("\t.long %s\n",s); +#endif +} + +extern void +emit_label(int labelno) +{ + data_mode(0); + printf("\t.long _%d\n",labelno); +} + +extern void +emit_data_closing(NMTBL *n) +{ +#ifdef DOT_SIZE + int lb; +#endif + if (mode==GDECL) { + data_mode(0); +#ifdef DOT_SIZE + lb=fwdlabel(); + printf("_%d:\n",lb); + printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm); +#endif + } +} + +#if LONGLONG_CODE +static long long ll0 = 1LL; + +static int +code_l1(long long d) +{ + int *i = (int *)&ll0; int *j = (int *)&d; + return (i[1] == 1)?j[1]:j[0]; +} + +static int +code_l2(long long d) +{ + int *i = (int *)&ll0; int *j = (int *)&d; + return (i[1] == 1)?j[0]:j[1]; +} +#endif + +void +global_table(void) +{ +#ifndef __APPLE__ + NMTBL *n; + int init; + init=0; + for(n=global_list;n;n = n->next) { + if (is_code(n) || is_function(n)) { + } + if ((n->sc == GVAR||n->sc == STATIC) && n->dsp != -1) { + if (is_code(n)||is_function(n)) continue; + /* n->dsp = -1 means initialized global */ + if (init==0) { + data_mode(0); + init=1; + } + printf(".comm %s,%d\n",n->nm,size(n->ty)); + // .lcomm? + } + } + +#else + + NMTBL *n; + int init; + init=0; + for(n=global_list;n;n = n->next) { + if ((n->sc == GVAR) && n->dsp != -1) { + if (is_code(n)||is_function(n)) continue; + /* n->dsp = -1 means initialized global */ + if (init==0) { + data_mode(0); + init=1; + } + printf(".comm _%s,%d\n",n->nm,size(n->ty)); + } else if ((n->sc==STATIC) && n->dsp != -1) { + /* n->dsp = -1 means initialized global */ + if (is_code(n)||is_function(n)) { + printf("\t.set L_%s$stub,_%s\n",n->nm,n->nm); + continue; + } + if (init==0) { + data_mode(0); + init=1; + } + printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); + } + } + init=0; + for(n = global_list;n!=&null_nptr;n = n->next) { + if (n->sc == GVAR || + ((is_code(n) || is_function(n)) &&has_attr(n,FNAME)) ) { + if (init==0) { + printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n"); + init=1; + } + printf("L_%s$non_lazy_ptr:\n\t.indirect_symbol _%s\n\t.long\t0\n", + n->nm,n->nm); + } + } + for(n = global_list;n!=&null_nptr;n = n->next) { + if (n->sc==EXTRN1) { + if (!(is_code(n) || is_function(n))) { + printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n"); + printf("L_%s$non_lazy_ptr:\n\t.indirect_symbol _%s\n\t.long\t0\n", + n->nm,n->nm); + } + printf("\t.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5\n"); + printf("L_%s$stub:\n",n->nm); + printf("\t.indirect_symbol _%s\n",n->nm); + printf("\thlt ; hlt ; hlt ; hlt ; hlt\n"); + } + } + printf(" .subsections_via_symbols\n"); + printf(" .section __TEXT,__textcoal_nt,coalesced,pure_instructions\n"); + printf(".weak_definition ___i686.get_pc_thunk.bx\n"); + printf(".private_extern ___i686.get_pc_thunk.bx\n"); + printf("___i686.get_pc_thunk.bx:\n"); + printf(" movl (%%esp), %%ebx\n"); + printf(" ret\n"); +#endif +} + + +void +local_table(void) +{ + NMTBL *n; + int init; + init=0; + /* static local variables */ + for(n=local_static_list;n;n = n->next) { + if (n->sc == STATIC) { + if (init==0) { + data_mode(0); + init=1; + } +#ifdef __APPLE__ + if (n->dsp!= -1) /* -1 means initialized global */ + printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); +#else + if (n->dsp!= -1) /* -1 means initialized global */ + printf(".lcomm %s,%d\n",n->nm,size(n->ty)); +#endif + } + } +} + +void +cstring_mode(int align) +{ + if (output_mode!=RODATA_EMIT_MODE) { +#ifndef __APPLE__ + printf(".section\t.rodata\n\t.align 2\n"); +#else + printf("\t.cstring\n"); +#endif + output_mode = RODATA_EMIT_MODE; + } +} + +void +text_mode(int align) +{ + if (output_mode!=TEXT_EMIT_MODE) { + printf(".text\n"); + // printf("\t.align 2\n"); + output_mode = TEXT_EMIT_MODE; + } +} + +void +data_mode(char *name) +{ + if (output_mode!=DATA_EMIT_MODE) { + printf(".data\n"); + output_mode = DATA_EMIT_MODE; + } +#ifndef __APPLE__ + if (name) + printf("\t.type\t%s,@object\n",name); +#endif +} + +#if FLOAT_CODE + +/* floating point */ + + +char * +fstore(int d) +{ + return use? + (d?"fstl":"fsts"): + (d?"fstpl":"fstps") + ; +} + +char * +fstore_u(int d) +{ + return d?"fstpl":"fstps"; +} + +char * +fload(int d) +{ + return d?"fldl":"flds"; +} + + +void code_dassign_gvar(int e2,int freg,int d) +{ +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e2)); + if (cadr(e2)) + printf("\t%s %d(%s)\n",fstore(d),cadr(e2),register_name(r,0)); + else + printf("\t%s (%s)\n",fstore(d),register_name(r,0)); +#else + if (cadr(e2)) + printf("\t%s %s+%d\n",fstore(d),(ncaddr(e2))->nm,cadr(e2)); + else + printf("\t%s %s\n",fstore(d),(ncaddr(e2))->nm); +#endif +} + +void code_dassign_lvar(int e2,int freg,int d) +{ + printf("\t%s ",fstore(d)); lvar(e2); printf("\n"); +} + +void code_dassign_dregister(int e,int d,int freg) +{ + error(-1); +} + +void code_dassign(int e2,int freg,int d) +{ + printf("\t%s (%s)\n",fstore(d),register_name(e2,0)); +} + +static double d0 = 1.0; + +static int +code_d1(double d) +{ + int *i = (int *)&d0; int *j = (int *)&d; + return (i[1] == 0x3ff00000)?j[0]:j[1]; +} + +static int +code_d2(double d) +{ + int *i = (int *)&d0; int *j = (int *)&d; + return (i[1] == 0x3ff00000)?j[1]:j[0]; +} + +void code_dconst(int e2,int freg,int d) +{ + int lb; + double value = dcadr(e2); + + if (value==0.0) { + printf("\tfldz\n"); return; + } + if (value==1.0) { + printf("\tfld1\n"); return; + } +#ifdef __APPLE__ + printf(" \t.literal8\n\t.align 3\n"); +#else + printf(" \t.section\t.rodata\n\t.align 8\n"); +#endif + lb=fwdlabel(); + printf("_%d:\n",lb); +#if ENDIAN_D==0 + printf("\t.long\t0x%x,0x%x\n",code_d1(value),code_d2(value)); +#endif + if (output_mode==TEXT_EMIT_MODE) { + printf(".text\n"); + } else { + text_mode(0); + } +#ifdef __APPLE__ + printf("\tfldl _%d-_%d(%%ebx)\n",lb,goffset_label); +#else + printf("\tfldl _%d\n",lb); +#endif +} + +void +code_builtin_fabsf(int e) +{ +} +void +code_builtin_fabs(int e) +{ +} +void +code_builtin_inff() +{ +} +void +code_builtin_inf() +{ +} + +void code_dneg(int freg,int d) +{ + printf("\tfchs\n"); +} + +void code_d2i(int reg) +{ + use_int(reg); + printf("\tlea -%d(%%esp),%%esp\n",SIZE_OF_INT*2); + printf("\tfnstcw (%%esp)\n"); + printf("\tmovl (%%esp), %s\n",register_name(creg,0)); + printf("\tmovb $12, 1(%%esp)\n"); + printf("\tfldcw (%%esp)\n"); + printf("\tfistpl %d(%%esp)\n",SIZE_OF_INT); + printf("\tmovl %s, (%%esp)\n",register_name(creg,0)); + printf("\tfldcw (%%esp)\n"); + printf("\tpopl %s\n",register_name(creg,0)); + printf("\tpopl %s\n",register_name(creg,0)); +} + +void code_i2d(int reg) +{ + printf("\tpushl %s\n",register_name(creg,0)); + printf("\tfildl (%%esp)\n"); + printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT); +} + +void code_d2u(int reg) +{ + use_int(reg); + printf("\tlea -%d(%%esp),%%esp\n",SIZE_OF_INT*3); + printf("\tfnstcw (%%esp)\n"); + printf("\tmovl (%%esp), %s\n",register_name(reg,0)); + printf("\tmovb $12, 1(%%esp)\n"); + printf("\tfldcw (%%esp)\n"); + printf("\tmovl %s, (%%esp)\n",register_name(reg,0)); + printf("\tfistpll %d(%%esp)\n",SIZE_OF_INT); + printf("\tfldcw (%%esp)\n"); + printf("\tmovl %d(%%esp),%s\n",SIZE_OF_INT,register_name(reg,0)); + printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT*3); +} + +void code_u2d(int reg) +{ + printf("\tpushl %s\n",register_name(creg,0)); + printf("\tpushl %s\n",register_name(creg,0)); + printf("\tmovl $0, %d(%%esp)\n",SIZE_OF_INT); + printf("\tfildll (%%esp)\n"); + printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT*2); +} + +void code_d2f(int reg) { } +void code_f2d(int reg) { } +void code_f2i(int reg) { code_d2i(reg); } +void code_f2u(int reg) { code_d2u(reg); } +void code_i2f(int reg) { code_i2d(reg); } +void code_u2f(int reg) { code_u2d(reg); } + +void code_drgvar(int e2,int d,int freg) +{ +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e2)); + if (cadr(e2)) + printf("\t%s %d(%s)\n",fload(d),cadr(e2),register_name(r,0)); + else + printf("\t%s (%s)\n",fload(d),register_name(r,0)); +#else + if (cadr(e2)) + printf("\t%s %s+%d\n",fload(d),(ncaddr(e2))->nm,cadr(e2)); + else + printf("\t%s %s\n",fload(d),(ncaddr(e2))->nm); +#endif +} + + +void code_drlvar(int e2,int d,int freg) +{ + printf("\t%s ",fload(d)); lvar(e2); printf("\n"); +} + +void code_cmp_drgvar(int e2,int reg,int d,int label,int cond) +{ +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e2)); + if (cadr(e2)) + printf("\tfcomp %d(%s)\n",cadr(e2),register_name(r,0)); + else + printf("\tfcomp (%s)\n",register_name(r,0)); +#else + if (cadr(e2)) + printf("\tfcomp %s+%d\n",(ncaddr(e2))->nm,cadr(e2)); + else + printf("\tfcomp %s\n",(ncaddr(e2))->nm); +#endif + jcond(label,cond); +} + +void code_cmp_drlvar(int e2,int reg,int d,int label,int cond) +{ + printf("\tfcomp "); lvar(e2); printf("\n"); + jcond(label,cond); +} + +void dtosop(int op,int reg,int e1) +{ + switch(op) { + case FADD: + case DADD: printf("\tfaddp %%st,%%st(1)\n"); break; + case FSUB: + case DSUB: printf("\tfsubp %%st,%%st(1)\n"); break; + case FDIV: + case DDIV: printf("\tfdivp %%st,%%st(1)\n"); break; + case FMUL: + case DMUL: printf("\tfmulp %%st,%%st(1)\n"); break; + case FCMP: + case DCMP: + printf("\tfucompp\n"); + printf("\tfnstsw\t%%ax\n"); +#ifdef __APPLE__ + if (regs[REG_EAX]==PTRC_REG) + clear_ptr_cache_reg(REG_EAX); +#endif + break; + } +} + +void +code_dassop(int op,int reg,int d) { + /* we have lvalue in creg, applied floating value is in %st(0) */ + emit_dpop(d); /* do nothing for 387 */ + printf("\t%s (%s)\n",fload(d),register_name(creg,0)); + dtosop(op,reg,0); + printf("\t%s (%s)\n",fstore(d),register_name(creg,0)); +} + +void +code_register_dassop(int reg,int op,int d) { + error(-1); +} + +void +code_dpreinc(int e1,int e2,int d,int freg) { + g_expr(e2); + printf("\t%s (%s)\n",fload(d),register_name(creg,0)); + printf("\tfld1\n"); + if (caddr(e1)>0) + printf("\tfaddp %%st,%%st(1)\n"); + else + printf("\tfsubrp %%st,%%st(1)\n"); + printf("\t%s (%s)\n",fstore(d),register_name(creg,0)); +} + +void +code_dpostinc(int e1,int e2,int d,int freg) { + g_expr(e2); + printf("\t%s (%s)\n",fload(d),register_name(creg,0)); + if (use) + printf("\t%s (%s)\n",fload(d),register_name(creg,0)); + printf("\tfld1\n"); + if (caddr(e1)>0) + printf("\tfaddp %%st,%%st(1)\n"); + else + printf("\tfsubrp %%st,%%st(1)\n"); + printf("\t%s (%s)\n",(use?fstore_u(d):fstore(d)),register_name(creg,0)); +} + +#define COND_BRANCH 1 +#define COND_VALUE 2 + +/* return 1 if boolean expression */ + +int +drexpr0(int e1, int e2,int l1, int op,int cond,int reg,int mode) +{ + char *s; + if (!cond) { + switch(op) { + case FOP+GT: + return drexpr0(e2,e1,l1,FOP+GE,1,reg,mode); + case FOP+GE: + return drexpr0(e2,e1,l1,FOP+GT,1,reg,mode); + case FOP+EQ: + op=FOP+NEQ; break; + case FOP+NEQ: + op=FOP+EQ; break; + case DOP+GT: + return drexpr0(e2,e1,l1,DOP+GE,1,reg,mode); + case DOP+GE: + return drexpr0(e2,e1,l1,DOP+GT,1,reg,mode); + case DOP+EQ: + op=DOP+NEQ; break; + case DOP+NEQ: + op=DOP+EQ; break; + default: return 0; + } + } + s = "e"; + switch(op) { + case DOP+GE: + case FOP+GE: + g_expr(list3(DCMP,e1,e2)); + printf("\ttestb\t$5,%%ah\n"); + break; + case DOP+GT: + case FOP+GT: + g_expr(list3(DCMP,e1,e2)); + printf("\ttestb\t$69,%%ah\n"); + break; + case DOP+EQ: + case FOP+EQ: + g_expr(list3(DCMP,e1,e2)); + printf("\tandb\t$69,%%ah\n"); + printf("\txorb\t$64,%%ah\n"); + break; + case DOP+NEQ: + case FOP+NEQ: + g_expr(list3(DCMP,e1,e2)); + printf("\tandb\t$69,%%ah\n"); + printf("\txorb\t$64,%%ah\n"); + s = "ne"; + break; + default: + return 0; + } + if (mode==COND_BRANCH) { + printf("\tj%s\t_%d\n",s,l1); + } else { + use_data_reg(reg,0); + printf("\tset%s\t%s\n",s,register_name(reg,1)); + printf("\tmovzbl\t%s,%s\n", + register_name(reg,1),register_name(reg,0)); + } + return 1; +} + +int +drexpr(int e1, int e2,int l1, int op,int cond) +{ + drexpr0(e1, e2,l1, op,cond,USE_CREG,COND_BRANCH); + return l1; +} + +static int +drexpr_bool(int e1, int reg) +{ + return drexpr0(cadr(e1), caddr(e1),0, car(e1),1,reg,COND_VALUE); +} + + +void +code_dregister(int e2,int freg,int d) +{ + error(-1); +} + +void +code_cmp_dregister(int e2,int d,int label,int cond) +{ + if (e2!=USE_CREG) + error(-1); +#ifdef __APPLE__ + if (regs[REG_EAX]==PTRC_REG) + clear_ptr_cache_reg(REG_EAX); +#endif + printf("\tfldz\n"); + printf("\tfucompp\n"); + printf("\tfnstsw\t%%ax\n"); + printf("\tandb\t$69,%%ah\n"); + printf("\txorb\t$64,%%ah\n"); + jcond(label,cond); +} + +int pop_fregister() +{ + if (freg_sp<0) { error(-1); return -1;} + // printf("## fpop: %d\n",freg_sp-1); + return freg_stack[--freg_sp]; +} + +int +emit_dpop(int d) +{ + int xreg; + if ((xreg=pop_fregister())==-1) { + } else if (xreg<= -REG_LVAR_OFFSET) { + code_drlvar(REG_LVAR_OFFSET+xreg,1,freg); + free_lvar(xreg+REG_LVAR_OFFSET); + /* pushed order is reversed. We don't need this for commutable + operator, but it is ok to do this. */ + printf("\tfxch\t%%st(1)\n"); + } + return xreg; +} + + +void emit_dpop_free(int e1,int d) +{ +} + +void emit_dpush(int type) +{ + if (freg_sp>=MAX_FPU_STACK) code_save_fstacks(); + if (freg_sp>MAX_MAX) error(-1); + freg_stack[freg_sp++]=-1; + // printf("## fpush:%d\n",freg_sp); +} + +#endif + +void +code_save_stacks() +{ + /* registers stacks are saved in local variable */ + int i,reg; + for(i=0;i<reg_sp;i++) { + if ((reg=reg_stack[i])>=0) { + code_assign_lvar( + (reg_stack[i]=new_lvar(SIZE_OF_INT)),reg,0); + reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; + if (regs[reg]!=REG_VAR) free_register(reg); + } + } +#if FLOAT_CODE + code_save_fstacks(); +#endif +} + +static void +code_clear_stack_reg(int reg1) +{ + /* specified registers stacks are saved in local variable */ + /* temporal registers are saved in local variable */ + int i,reg; + if (regs[reg1]==PTRC_REG) + clear_ptr_cache_reg(reg1); + + for(i=0;i<reg_sp;i++) { + if ((reg=reg_stack[i])>=0 && reg==reg1) { + code_assign_lvar( + (reg_stack[i]=new_lvar(SIZE_OF_INT)),reg,0); + reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; + if (regs[reg]!=REG_VAR) free_register(reg); + } + } +} + +#if FLOAT_CODE +void +code_save_fstacks() +{ + /* stacks in fpu are saved in local variable */ + int xreg,sp,uses; + uses = use; use = 0; + sp=freg_sp; + while(sp-->0) { + if ((xreg=freg_stack[sp])==-1) { + code_dassign_lvar( + (freg_stack[sp]=new_lvar(SIZE_OF_DOUBLE)),freg,1); + freg_stack[sp]= freg_stack[sp]-REG_LVAR_OFFSET; + } + } + use = uses; +} +#endif + + + +#if LONGLONG_CODE + + +/* 64bit int part */ + +static void +pcond(char *s,int l1) +{ + printf("\tj%s\t_%d\n",s,l1); +} + +int +lrexpr(int e1, int e2,int l1, int op,int cond) +{ + int l2; + code_save_stacks(); + g_expr(e1); + emit_lpush(); + g_expr(e2); + // we are sure %ecx is free + // %ebx is used in Intel Mac + stack_depth -= SIZE_OF_INT * 2; + printf("\tpopl %%ecx\n"); // LSW + printf("\tcmpl %%edx,(%%esp)\n"); // MSW + printf("\tpopl %%edx\n"); + l2 = fwdlabel(); + // cond==0 jump on false condtion ( if(x) => rexpr(.. cond=0 ...) ) + switch(op) { + case LOP+GT: + case LOP+GE: + pcond(code_gt(1),cond?l1:l2); + pcond(code_eq(0),cond?l2:l1); + break; + case LOP+UGT: + case LOP+UGE: + pcond(code_ugt(1),cond?l1:l2); + pcond(code_eq(0), cond?l2:l1); + break; + case LOP+EQ: + pcond(code_eq(0),(cond?l2:l1)); + break; + case LOP+NEQ: + pcond(code_eq(0),(cond?l1:l2)); + break; + default: + error(-1); + } + printf("\tsubl %%eax,%%ecx\n"); + switch(op) { + case LOP+GT: pcond(code_gt(cond), l1); break; + case LOP+GE: pcond(code_ge(cond), l1); break; + case LOP+UGT: pcond(code_ugt(cond), l1); break; + case LOP+UGE: pcond(code_uge(cond), l1); break; + case LOP+EQ: pcond(code_eq(cond),l1); break; + case LOP+NEQ: pcond(code_eq(!cond),l1); break; + } + fwddef(l2); + return l1; +} + +int emit_lpop() +{ + return 0; +} + +void code_lregister(int e2,int reg) +{ + use_longlong(reg); + if (reg!=REG_L) { + printf("\tmovl %%esi,%s\n",l_eax(reg)); + printf("\tmovl %%edi,%s\n",l_edx(reg)); + } +} + +void code_cmp_lregister(int reg,int label,int cond) +{ + char *crn; + use_int(reg); + crn = register_name(reg,0); + printf("\tmovl %%esi,%s\n",crn); + printf("\torl %%edi,%s\n",crn); + printf("\ttestl %s,%s\n",crn,crn); + jcond(label,cond); +} + +void code_cmp_lrgvar(int e1,int e2,int label,int cond) +{ + char *n,*crn; + use_int(e2); + crn = register_name(e2,0); +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e1)); + n = register_name(r,0); + if (cadr(e1)) { + printf("\tmovl %d(%s),%s\n",cadr(e1),n,crn); + printf("\torl %d(%s),%s\n",cadr(e1)+4,n,crn); + } else { + printf("\tmovl (%s),%s\n",n,crn); + printf("\torl 4(%s),%s\n",n,crn); + } +#else + n = (ncaddr(e1))->nm; + if (cadr(e1)) { + printf("\tmovl %s+%d,%s\n",n,cadr(e1),crn); + printf("\torl %s+%d,%s\n",n,cadr(e1)+4,crn); + } else { + printf("\tmovl %s,%s\n",n,crn); + printf("\torl %s+4,%s\n",n,crn); + } +#endif + printf("\ttestl %s,%s\n",crn,crn); + jcond(label,cond); +} + +void code_cmp_lrlvar(int e1,int e2,int label,int cond) +{ + char *crn; + use_int(e2); + crn = register_name(e2,0); + printf("\tmovl "); lvar(e1); printf(",%s\n",crn); + printf("\torl "); lvar(e1+4); printf(",%s\n",crn); + printf("\ttestl %s,%s\n",crn,crn); + jcond(label,cond); +} + +void code_lassign(int e1,int e2) +{ + char *rn; + // e1 = e2 + use_longlong(e2); + rn = register_name(e1,0); +#if ENDIAN_L==0 + printf("\tmovl %s,(%s)\n",l_eax(e2),rn); + printf("\tmovl %s,4(%s)\n",l_edx(e2),rn); +#endif +} + +void code_lassign_gvar(int e1,int e2) +{ + char *n; + use_longlong(e2); +#if ENDIAN_L==0 +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e1)); + n = register_name(r,0); + if (cadr(e1)) { + printf("\tmovl %s,%d(%s)\n",l_eax(e2),cadr(e1),n); + printf("\tmovl %s,%d(%s)\n",l_edx(e2),cadr(e1)+4,n); + } else { + printf("\tmovl %s,(%s)\n",l_eax(e2),n); + printf("\tmovl %s,4(%s)\n",l_edx(e2),n); + } +#else + n = (ncaddr(e1))->nm; + if (cadr(e1)) { + printf("\tmovl %s,%s+%d\n",l_eax(e2),n,cadr(e1)); + printf("\tmovl %s,%s+%d\n",l_edx(e2),n,cadr(e1)+4); + } else { + printf("\tmovl %s,%s\n",l_eax(e2),n); + printf("\tmovl %s,%s+4\n",l_edx(e2),n); + } +#endif +#endif +} + +void code_lassign_lvar(int e1,int e2) +{ + use_longlong(e2); +#if ENDIAN_L==0 + printf("\tmovl %s,",l_eax(e2)); lvar(e1); printf("\n"); + printf("\tmovl %s,",l_edx(e2)); lvar(e1+4); printf("\n"); +#endif +} + +void code_lassign_lregister(int e2,int reg) +{ + // e2 = reg + use_longlong(reg); + if (e2!=reg) { + printf("\tmovl %s,%s\n",l_eax(reg),l_eax(e2)); + printf("\tmovl %s,%s\n",l_edx(reg),l_edx(e2)); + } +} + +void +code_lconst(int e1,int creg) +{ + use_longlong(creg); +#if ENDIAN_L==0 + printf("\tmovl $%d,%s\n",code_l1(lcadr(e1)),l_eax(creg)); + printf("\tmovl $%d,%s\n",code_l2(lcadr(e1)),l_edx(creg)); +#endif +} + +void code_lneg(int e1) +{ + use_longlong(e1); + printf("\tnegl %s\n",l_eax(e1)); + printf("\tadcl $0,%s\n",l_edx(e1)); + printf("\tnegl %s\n",l_edx(e1)); +} + +void code_lrgvar(int e1,int e2) +{ + char *n; + use_longlong(e2); +#if ENDIAN_L==0 +#ifdef __APPLE__ + int r = get_ptr_cache(ncaddr(e1)); + n = register_name(r,0); + if (cadr(e1)) { + printf("\tmovl %d(%s),%s\n",cadr(e1),n,l_eax(e2)); + printf("\tmovl %d(%s),%s\n",cadr(e1)+4,n,l_edx(e2)); + } else { + printf("\tmovl (%s),%s\n",n,l_eax(e2)); + printf("\tmovl 4(%s),%s\n",n,l_edx(e2)); + } +#else + n = (ncaddr(e1))->nm; + if (cadr(e1)) { + printf("\tmovl %s+%d,%s\n",n,cadr(e1),l_eax(e2)); + printf("\tmovl %s+%d,%s\n",n,cadr(e1)+4,l_edx(e2)); + } else { + printf("\tmovl %s,%s\n",n,l_eax(e2)); + printf("\tmovl %s+4,%s\n",n,l_edx(e2)); + } +#endif +#endif +} + +void code_lrlvar(int e1,int e2) +{ + use_longlong(e2); +#if ENDIAN_L==0 + printf("\tmovl "); lvar(e1); printf(",%s\n",l_eax(e2)); + printf("\tmovl "); lvar(e1+4); printf(",%s\n",l_edx(e2)); +#endif +} + +#define check_lreg(reg) if (reg==REG_L) code_lassign_lregister(reg,REG_LCREG) + +void +ltosop(int op,int reg,int e2) +{ + char *opl,*oph,*call; + int lb; + + // e2 (operand) is on the top of the stack + use_longlong(reg); + opl = 0; call=0; + stack_depth -= SIZE_OF_INT * 2; + + switch(op) { + case LLSHIFT: + case LULSHIFT: + printf("\tmovl %%ecx,4(%%esp)\n"); + printf("\tpopl %%ecx\n"); + printf("\tshldl %%eax,%%edx\n"); + printf("\tsall %%cl,%%eax\n"); + printf("\ttestb $32,%%cl\n"); + printf("\tje\t_%d\n",(lb=fwdlabel())); + printf("\tmovl %%eax,%%edx\n"); + printf("\txorl %%eax,%%eax\n"); + fwddef(lb); + printf("\tpopl %%ecx\n"); + check_lreg(reg); + return; + case LRSHIFT: + printf("\tmovl %%ecx,4(%%esp)\n"); + printf("\tpopl %%ecx\n"); + printf("\tshrdl %%edx,%%eax\n"); + printf("\tsarl %%cl,%%edx\n"); + printf("\ttestb $32,%%cl\n"); + printf("\tje\t_%d\n",(lb=fwdlabel())); + printf("\tmovl %%edx,%%eax\n"); + printf("\tsarl $31,%%edx\n"); + fwddef(lb); + printf("\tpopl %%ecx\n"); + check_lreg(reg); + return; + case LURSHIFT: + printf("\tmovl %%ecx,4(%%esp)\n"); + printf("\tpopl %%ecx\n"); + printf("\tshrdl %%edx,%%eax\n"); + printf("\tshrl %%cl,%%edx\n"); + printf("\ttestb $32,%%cl\n"); + printf("\tje\t_%d\n",(lb=fwdlabel())); + printf("\tmovl %%edx,%%eax\n"); + printf("\txorl %%edx,%%edx\n"); + fwddef(lb); + printf("\tpopl %%ecx\n"); + check_lreg(reg); + return; + } + switch(op) { + case LADD: opl="addl";oph="adcl"; break; + case LSUB: opl="subl";oph="sbbl"; break; + case LBAND: opl=oph="andl"; break; + case LEOR: opl=oph="xorl"; break; + case LBOR: opl=oph="orl"; break; + case LMUL: + case LUMUL: + printf("\tpushl %%edx\n"); + printf("\tpushl %%eax\n"); + printf("\tpushl %%ecx\n"); + // 0 saved ecx + // 4 c_l + // 8 c_h + // 12 o_l + // 16 o_h + printf("\tmull 12(%%esp)\n"); // c_l*o_l -> %edx,%eax + printf("\tmovl 4(%%esp),%%ecx\n"); // c_l->%ecx + printf("\timull 16(%%esp),%%ecx\n"); // c_l*o_h->%ecx + printf("\taddl %%ecx,%%edx\n"); // %edx+%ecx->%edx + printf("\tmovl 8(%%esp),%%ecx\n"); // c_h->%ecx + printf("\timull 12(%%esp),%%ecx\n"); // c_h*o_l->%ecx + printf("\taddl %%ecx,%%edx\n"); // %edx+%ecx->%edx + printf("\tpopl %%ecx\n"); + // printf("\taddl $8,%%esp\n"); + printf("\tlea 16(%%esp),%%esp\n"); + return; +#ifdef __APPLE__ + case LDIV: call="L___divdi3$stub"; + extern_define("__divdi3",0,FUNCTION,1); break; + case LUDIV: call="L___udivdi3$stub"; + extern_define("__udivdi3",0,FUNCTION,1); break; + case LMOD: call="L___moddi3$stub"; + extern_define("__moddi3",0,FUNCTION,1); break; + case LUMOD: call="L___umoddi3$stub"; + extern_define("__umoddi3",0,FUNCTION,1); break; +#else + case LDIV: call="__divdi3"; break; + case LUDIV: call="__udivdi3"; break; + case LMOD: call="__moddi3"; break; + case LUMOD: call="__umoddi3"; break; +#endif + default: error(-1); + } + if (opl) { + printf("\t%s (%%esp),%%eax\n\t%s 4(%%esp),%%edx\n",opl,oph); + printf("\tlea 8(%%esp),%%esp\n"); + check_lreg(reg); + } else if (call) { +#ifdef __APPLE__ + clear_ptr_cache(); + printf("\tpushl %%edx\n"); + printf("\tpushl %%eax\n"); + printf("\tcall %s\n",call); + printf("\tlea 16(%%esp),%%esp\n"); +#else + printf("\tpushl %%edx\n"); + printf("\tpushl %%eax\n"); + printf("\tcall %s\n",call); + printf("\tlea 16(%%esp),%%esp\n"); +#endif + check_lreg(reg); + } else { + error(-1); + } +} + +int code_lconst_op_p(int op,int e) { + long long l; + if (car(e)==CONST) l = cadr(e); + else if (car(e)==LCONST) l = lcadr(e); + else return 0; + + switch(op) { + case LLSHIFT: + case LULSHIFT: + case LRSHIFT: + case LURSHIFT: + return (0<=l&&l<=63); + case LMUL: + case LUMUL: + case LUDIV: + /* case LDIV: */ + return -0x10000000LL<l&&l<0x10000000LL && ilog(l); + case LADD: + case LSUB: + case LBAND: + case LEOR: + case LBOR: + return 1; + default: + return 0; + } +} + +void loprtc(int op,int reg,int e) { + char *opl,*oph=0; + int vl,il; + int vh; + long long l=0; + + if (car(e)==CONST) l = cadr(e); + else if (car(e)==LCONST) l = lcadr(e); + else error(-1); + + vl = code_l1(l); + vh = code_l2(l); + il = l; + + use_longlong(reg); + opl = 0; + + switch(op) { + case LMUL: case LUMUL: + vl=il=ilog(il); + case LLSHIFT: + case LULSHIFT: + if (il==0) return; + else if (il==32) { + code_register(regv_l(reg),regv_h(reg)); + code_const(0,regv_l(reg)); + return; + } else if (il>32) { + code_register(regv_l(reg),regv_h(reg)); + printf("\tsall $%d,%s\n",(int)il-32,l_edx(reg)); + code_const(0,regv_l(reg)); + return; + } + printf("\tshldl $%d,%s,%s\n",vl,l_eax(reg),l_edx(reg)); + printf("\tsall $%d,%s\n",(int)il,l_eax(reg)); return; + case LRSHIFT: + if (il==0) return; + else if (il==32) { + code_register(regv_h(reg),regv_l(reg)); + creg = ireg = REG_EAX; + code_i2ll(reg); + return; + } else if (il>32) { + code_register(regv_h(reg),regv_l(reg)); + printf("\tsarl $%d,%s\n",(int)il-32,l_eax(reg)); + creg = ireg = REG_EAX; + code_i2ll(reg); + return; + } + printf("\tshrdl $%d,%s,%s\n",(int)il,l_edx(reg),l_eax(reg)); + printf("\tsarl $%d,%s\n",(int)il,l_edx(reg)); + return; + case LUDIV: + il=ilog(il); + case LURSHIFT: + if (il==0) return; + else if (il==32) { + code_register(regv_h(reg),regv_l(reg)); + code_const(0,regv_h(reg)); + return; + } else if (il>32) { + if (il>64) error(-1); + code_register(regv_h(reg),regv_l(reg)); + printf("\tsarl $%d,%s\n",(int)il-32,l_eax(reg)); + code_const(0,regv_h(reg)); + return; + } + printf("\tshrdl $%d,%s,%s\n",(int)il,l_edx(reg),l_eax(reg)); + printf("\tshrl $%d,%s\n",(int)il,l_edx(reg)); + return; + } + switch(op) { + case LADD: opl="addl";oph="adcl"; break; + case LSUB: opl="subl";oph="sbbl"; break; + case LEOR: opl=oph="xorl"; break; + case LBOR: opl=oph="orl"; break; + case LBAND: opl=oph="andl"; break; + default: error(-1); + } + printf("\t%s $%d,%s\n\t%s $%d,%s\n",opl,vl,l_eax(reg),oph,vh,l_edx(reg)); +} + +void emit_lpop_free(int e1) +{ +// printf("\taddl $8,%%esp\n"); +} + +void emit_lpush() +{ + stack_depth += SIZE_OF_INT * 2; + printf("\tpushl %%edx\n\tpushl %%eax\n"); +} + +void code_i2ll(int reg) +{ + int reg0 = USE_CREG; + int creg0 = creg; + + use_longlong(reg0); + use_register(creg0,REG_EAX,1); + + printf("\tcltd\n"); + check_lreg(reg); + lreg = creg = reg0; +} + +void code_i2ull(int reg) +{ + code_i2ll(reg); +} + +void code_u2ll(int reg) +{ + int reg0 = USE_CREG; + int creg0 = creg; + + use_longlong(reg0); + use_register(creg0,REG_EAX,1); + + use_longlong(reg0); + printf("\txorl %%edx,%%edx\n"); + check_lreg(reg); + lreg = creg = reg0; +} + +void code_u2ull(int reg) +{ + code_u2ll(reg); +} + +void code_ll2i(int reg) +{ + use_int(reg); + if (REG_EAX!=reg) + printf("\tmovl %%eax,%s\n",register_name(creg,0)); +} + +void code_ll2u(int reg) +{ + code_ll2i(reg); +} + +void code_ull2i(int reg) +{ + code_ll2i(reg); +} + +void code_ull2u(int reg) +{ + code_ll2i(reg); +} + +#if FLOAT_CODE +void code_d2ll(int reg) +{ + use_longlong(reg); +#if 1 + printf("\tsubl $64, %%esp\n"); + printf("\tfnstcw 34(%%esp)\n"); + printf("\tmovzwl 34(%%esp), %%eax\n"); + printf("\tmovb $12, %%ah\n"); + printf("\tmovw %%ax, 32(%%esp)\n"); + printf("\tfldcw 32(%%esp)\n"); + printf("\tfistpll 52(%%esp)\n"); + printf("\tfldcw 34(%%esp)\n"); + printf("\tmovl 52(%%esp), %%eax\n"); + printf("\tmovl 56(%%esp), %%edx\n"); + printf("\taddl $64, %%esp\n"); +#else + printf("\tsubl $40,%%esp\n"); + printf("\tfnstcw 2(%%esp)\n"); + printf("\tmovw 2(%%esp),%%ax\n"); + printf("\torw $3072,%%ax\n"); + printf("\tmovw %%ax,0(%%esp)\n"); + printf("\tfldcw 0(%%esp)\n"); + printf("\tfistpll 12(%%esp)\n"); + printf("\tfldcw 2(%%esp)\n"); + printf("\tmovl 12(%%esp),%%eax\n"); + printf("\tmovl 16(%%esp),%%edx\n"); + printf("\taddl $40,%%esp\n"); +#endif + check_lreg(reg); +} + +void code_d2ull(int reg) +{ + use_longlong(reg); +#ifdef __APPLE__ + clear_ptr_cache(); +#endif + printf("\tsubl $16,%%esp\n"); + printf("\tfstpl (%%esp)\n"); +#ifdef __APPLE__ + printf("\tcall L___fixunsdfdi$stub\n"); + extern_define("__fixunsdfdi",0,FUNCTION,1); +#else + printf("\tcall __fixunsdfdi\n"); +#endif + printf("\taddl $16,%%esp\n"); +} + +void code_f2ll(int reg) +{ + code_d2ll(reg); +} + +void code_f2ull(int reg) +{ + use_longlong(reg); +#ifdef __APPLE__ + clear_ptr_cache(); +#endif + printf("\tsubl $16,%%esp\n"); + printf("\tfstps (%%esp)\n"); +#ifdef __APPLE__ + printf("\tcall L___fixunssfdi$stub\n"); + extern_define("__fixunssfdi",0,FUNCTION,1); +#else + printf("\tcall __fixunssfdi\n"); +#endif + printf("\taddl $16,%%esp\n"); +} + +void code_ll2d(int reg) +{ + printf("\tsubl $8,%%esp\n"); + printf("\tmovl %%eax,(%%esp)\n"); + printf("\tmovl %%edx,4(%%esp)\n"); + printf("\tfildll (%%esp)\n"); + printf("\taddl $8,%%esp\n"); +} + +void code_ll2f(int reg) +{ + code_ll2d(reg); +} + +void code_ull2d(int reg) +{ + code_ll2d(reg); +} + +void code_ull2f(int reg) +{ + code_ll2d(reg); +} + +#endif + + +void code_lpreinc(int e1,int e2,int reg) +{ + int dir = caddr(e1); + int creg0; + char *crn; + if (car(e2)==LREGISTER) { + use_longlong(reg); + printf("\taddl $%d,%%esi\n",dir); + printf("\tadcl $%d,%%edi\n",dir>0?0:-1); + if (use && reg!=REG_L) { + code_lregister(REG_L,reg); + } + return; + } + g_expr(e2); + crn = register_name(creg0=creg,0); + printf("\taddl $%d,(%s)\n",dir,crn); + printf("\tadcl $%d,4(%s)\n",dir>0?0:-1,crn); + use_longlong(reg); + lload(creg0,0,reg); +} + +void code_lpostinc(int e1,int e2,int reg) +{ + int dir = caddr(e1); + int creg0; + char *crn; + if (car(e2)==LREGISTER) { + use_longlong(reg); + if (use && reg!=REG_L) { + code_lregister(REG_L,reg); + } + printf("\taddl $%d,%%esi\n",dir); + printf("\tadcl $%d,%%edi\n",dir>0?0:-1); + return; + } + g_expr(e2); + crn = register_name(creg0=creg,0); + printf("\taddl $%d,(%s)\n",dir,crn); + printf("\tadcl $%d,4(%s)\n",dir>0?0:-1,crn); + if (use) { + use_longlong(reg); + lload(creg0,0,reg); + printf("\taddl $%d,%s\n",-dir,l_eax(reg)); + printf("\tadcl $%d,%s\n",-dir>0?0:-1,l_edx(reg)); + } +} + +void code_lassop(int op,int reg) +{ + error(-1); +} + +void +code_register_lassop(int reg,int op) { + error(-1); +} + + +#endif + + + + + +#if CASE_CODE + +int +code_table_jump_p(int delta) { return 1; } + +void +code_table_jump(int l,int csvalue,int delta,int max,int min,int dlabel) +{ + char *crn; + // use_register(creg,csvalue,0); + set_ireg(csvalue,0); + crn = register_name(creg,0); + printf("\tsubl\t$%d,%s\n",min,crn); + printf("\tcmpl\t$%d,%s\n",max-min,crn); + printf("\tja\t_%d\n",dlabel); + if (delta==1) { +#ifdef __APPLE__ + printf("\tmovl\t_%d-_%d(%%ebx,%s,4),%s\n",l,goffset_label,crn,crn); + printf("\taddl\t%%ebx,%s\n",crn); + printf("\tjmp\t*%s\n",crn); +#else + printf("\tjmp\t*_%d(,%s,4)\n",l,crn); +#endif + return; + } +#ifdef __APPLE__ + if (regs[REG_EAX]==PTRC_REG) + clear_ptr_cache_reg(REG_EAX); +#endif + use_register(creg,REG_EAX,1); + crn = "%eax"; + + switch(delta) { + case 2: + printf("\tmovl\t$1,%%edx\n"); + printf("\tandl\t%%eax,%%edx\n"); + printf("\tjne\t_%d\n",dlabel); +#ifdef __APPLE__ + printf("\tmovl\t_%d-_%d(%%ebx,%s,2),%s\n",l,goffset_label,crn,crn); + printf("\taddl\t%%ebx,%s\n",crn); + printf("\tjmp\t*%s\n",crn); +#else + printf("\tjmp\t*_%d(,%%eax,2)\n",l); +#endif + break; + case 4: + printf("\tmovl\t$3,%%edx\n"); + printf("\tandl\t%%eax,%%edx\n"); + printf("\tjne\t_%d\n",dlabel); +#ifdef __APPLE__ + printf("\tmovl\t_%d-_%d(%%ebx,%s),%s\n",l,goffset_label,crn,crn); + printf("\taddl\t%%ebx,%s\n",crn); + printf("\tjmp\t*%s\n",crn); +#else + printf("\tjmp\t*_%d(%%eax)\n",l); +#endif + break; + default: + printf("\tmovl $%d,%%ecx\n",delta); + printf("\txor %%edx,%%edx\n\tdivl %%ecx\n"); + printf("\tandl\t%%edx,%%edx\n"); + printf("\tjne\t_%d\n",dlabel); +#ifdef __APPLE__ + printf("\tmovl\t_%d-_%d(%%ebx,%s,4),%s\n",l,goffset_label,crn,crn); + printf("\taddl\t%%ebx,%s\n",crn); + printf("\tjmp\t*%s\n",crn); +#else + printf("\tjmp\t*_%d(,%%eax,4)\n",l); +#endif + break; + } + +} + +void +code_table_open(int l) +{ + output_mode=DATA_EMIT_MODE; +#ifdef __APPLE__ + printf(" \t.align 2\n"); +#else + printf(" \t.section\t.rodata\n\t.align 4\n"); +#endif + fwddef(l); +} + +void +code_table_value(int label,int table_top) +{ +#ifdef __APPLE__ + printf("\t.long _%d-_%d\n",label,goffset_label); +#else + printf("\t.long _%d\n",label); +#endif +} + +void +code_table_close() +{ + text_mode(0); +} + +#endif + + +#if ASM_CODE + +/* + print an operand + */ + +static void +emit_asm_operand(int rstr) +{ + if (car(rstr)==REGISTER) { + printf("%s",register_name(cadr(rstr),0)); + } else if (car(rstr)==CONST) { + printf("%d",cadr(rstr)); + } else if (car(rstr)==FNAME) { +#ifdef __APPLE__ + printf("_%s-_%d",ncaddr(rstr)->nm,goffset_label); +#else + printf("%s",ncaddr(rstr)->nm); +#endif + } else if (car(rstr)==LABEL) { +#ifdef __APPLE__ + printf("_%d-_%d",cadr(rstr),goffset_label); +#else + printf("_%d",cadr(rstr)); +#endif + } else { + error(-1); + } +} + +/* + prepare asm operands + + char *constraints string + int operand expr + int mode (ASM_INPUT,ASM_OUTPUT) + int replacement list + int output operands count + int output operands replacement list + + retrun replacement list + list3( operands, next, clobber ) + 0 can be shared in input/output + 1 can't be used in input + */ + +int +code_asm_operand(char *p,int e1,int mode,int repl,int n,int repl0) +{ + int r; + int c; + int val; + int clobber = 0; + + printf("## constraint %s\n",p); + if (*p=='=') { + // output register + p++; + } + if (*p=='&') { + // earlyclobber + p++; + clobber = 1; + } + c = *p; + if (c=='r') { + if (mode==ASM_INPUT) { + for(;repl0;repl0 = cadr(repl0)) { + if (car(car(repl0))==REGISTER && caddr(repl0)==0) { + r = cadr(car(repl0)); + caddr(repl0) = ASM_USED; + break; + } + } + r = get_register(); + } else { + r = get_register(); + } + repl = list3(list2(REGISTER,r),repl,clobber); + } else if (c=='m') { + repl = list3(list2(0,0),repl,clobber); + } else if (c=='i') { + if (car(e1)==GVAR) { + e1=list3n(FNAME,0,ncaddr(e1)); + } else if (car(e1)==FNAME) { + e1=list3n(FNAME,0,ncaddr(e1)); + } else if (car(e1)==STRING) { + val = emit_string_label(); + ascii(ncaddr(e1)->nm); + e1=list2(LABEL,val); + } else if (car(e1)==CONST) { + } else error(-1); + repl = list3(e1,repl,clobber); + } else if (digit(c)) { + val = 0; + do { val = val*10 + c-'0'; } while (digit(c=*p++)); + if (val>MAX_ASM_REG) error(-1); // too large register + if (n-val<0) error(-1); + repl = list3(car(nth(n-val-1,repl0)),repl,clobber); + } else error(-1); + return repl; +} + +void +code_free_asm_operand(int repl) +{ + int reg; + for(;repl;repl=cadr(repl)) { + if (car(car(repl))==REGISTER) { + reg = cadr(car(repl)); + if (regs[reg]!=REG_VAR) free_register(reg); + } + } +} + + +extern void +code_asm(char *asm_str,int repl) +{ + int c,i,rstr,val; + char *p; + int reg[MAX_ASM_REG]; + + text_mode(0); + c = *asm_str; + if (c!='\t'&&c!=' ') printf("\t"); + for(i=0;repl && i<MAX_ASM_REG;i++) { + reg[i] = car(repl); + repl = cadr(repl); + } + p = asm_str; + while((c = *p++)) { + if (c=='%') { + c = *p++; + if (!c) { break; + } else if (c=='%') { + printf("%%"); continue; + } else if (!digit(c)) { + printf("%%%c",c); continue; + } + val = 0; + do { val = val*10 + c-'0'; } while (digit(c=*p++)) ; + p--; + if (val>MAX_ASM_REG) error(-1); // too large register + rstr = reg[val]; + emit_asm_operand(rstr); + } else { + printf("%c",c); + } + } + printf("\n"); +} + +#endif + + +#if BIT_FIELD_CODE + +/* bit field alignment calcuration */ + +static void +set_bitsz(int type,int *pbitpos, int *pbitsize, + int *psign,int *pbitsz,int *palign,int *pl) +{ + int sign=0,bitsz=1; + int align=4,l=0; + *pbitpos = cadr(caddr(type)); + *pbitsize = caddr(caddr(type)); + + switch(cadr(type)) { + case INT: sign=1; bitsz=32; align=4;break; + case UNSIGNED: bitsz=32; align=4;break; + case CHAR: sign=1; bitsz= 8; align=1;break; + case UCHAR: bitsz= 8; align=1;break; + case SHORT: sign=1; bitsz=16; align=2;break; + case USHORT: sign=1; bitsz=16; align=2;break; + case LONGLONG: sign=1; bitsz=64; align=4;l=1; break; + case ULONGLONG: bitsz=64; align=4;l=1; break; + default: error(-1); + } + *psign = sign; + *pbitsz = bitsz; + *palign = align; + *pl = l; +} + +/* + bit field alignment calcuration + this is architecture depenedent + */ + +extern int +code_bit_field_disp(int type,int *poffset,int *bfd,int *sz) +{ + int sign,bitsz,align; + int i; + int bitpos = *bfd; + int bitpos0; + int bitsize; + int offset = *poffset; + int l; + set_bitsz(type,&bitpos0,&bitsize,&sign,&bitsz,&align,&l); + + if (bitsize>bitsz) { error(BTERR); bitsize = bitsz; } + + /* bfd means previous bit field bit offset */ + if (bitpos) { + /* previous field is bit field and spaces may remain */ + /* calc previsous offset */ + + i= offset-(bitpos+7)/8; + + for(l = bitpos;l>0;l -= 8,i++) { + if ((i & (align-1))==0 && l+bitsize <= bitsz) { + /* alignment is correct and space remains */ + *poffset=offset=i; + i = l+bitsize; + *bfd = (i==bitsz)?0:i; + *sz = (i+7)/8; +// printf("## bitpos=%d bitsize=%d bitsz=%d offset=%d\n",l,bitsize,bitsz,*poffset); + return l; + } + } + } + + /* first bit-field */ + + if ((i=(offset & (align-1)))) { + *poffset = (offset += (align-i)); + } + bitpos = 0; + *bfd = (bitsize==bitsz)?0:bitsize; + *sz = (bitsize+7)/8; + +// printf("## bitpos=%d bitsize=%d bitsz=%d offset=%d\n",bitpos,bitsize,bitsz,*poffset); + return bitpos; +} + +/* bit field value */ + +extern void +code_bit_field(int type,int adr,int reg) +{ + int sign,bitsz,l,align; + int bitsize,bitpos; + int i,size; + set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l); + size=bitsz/8; +// printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); + /* this implementation returns -1 for int i:1; */ + if (l==1) { +#if LONGLONG_CODE + use_int(adr); + use_longlong(reg); + lload(adr,0,reg); + /* shift left */ + if ((i=bitsz-bitsize-bitpos)) + loprtc(LLSHIFT,reg,list2(CONST,i)); + /* shift right */ + if ((i=bitsz-bitsize)) + loprtc(sign?LRSHIFT:LURSHIFT,reg,list2(CONST,i)); +#endif + } else { + use_int(adr); + use_int(reg); + printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0), + register_name(reg,0)); + /* shift left */ + if ((i=32-bitsize-bitpos)) + oprtc(LSHIFT,reg,list2(CONST,i)); + /* shift right */ + if ((i=32-bitsize)) + oprtc(sign?RSHIFT:URSHIFT,reg,list2(CONST,i)); + } +} + +/* bit field replacement */ + +static void +make_mask_and_or(int mask,int reg,int lreg) +{ +printf("## mask 0x%08x ~0x%08x\n",mask,~mask); + printf("\tpushl %s\n",register_name(reg,0)); + /* make and-mask */ + oprtc(BOR,reg,list2(CONST,~mask)); + /* do conjunction */ + if (lreg==-1) { + printf("\tandl %s,4(%%esp)\n",register_name(reg,0)); + } else if (lreg==-2) { + printf("\tandl %s,8(%%esp)\n",register_name(reg,0)); + } else { + printf("\tandl %s,%s\n",register_name(reg,0),register_name(lreg,0)); + } + /* make or-mask */ + printf("\tpopl %s\n",register_name(reg,0)); + oprtc(BAND,reg,list2(CONST,mask)); + /* do disjunction */ + if (lreg==-1) { + printf("\torl %s,0(%%esp)\n",register_name(reg,0)); + } else if (lreg==-2) { + printf("\torl %s,4(%%esp)\n",register_name(reg,0)); + } else { + printf("\torl %s,%s\n",register_name(reg,0),register_name(lreg,0)); + printf("\txchg %s,%s\n",register_name(reg,0),register_name(lreg,0)); + } +} + +extern void +code_bit_replace(int adr,int value,int type) +{ + int sign,bitsz,l,align; + int bitsize,bitpos; + int mask = 0; + int size; + set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l); + size = bitsz/8; +// printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); + if (l) { +#if LONGLONG_CODE + int push=0; + use_int(adr); + use_longlong(value); + /* shift left */ + if (bitpos) + loprtc(LLSHIFT,value,list2(CONST,bitpos)); + if (bitpos+bitsize>=32) { + /* make and-mask upper */ + printf("\tpushl %s\n",register_name(adr,0)); push=1; + printf("\t%s %d(%s),%s\n",cload(sign,size),4,register_name(adr,0), + register_name(adr,0)); + mask = make_mask(64-bitpos-bitsize,bitpos>=32?63-bitpos:31); + make_mask_and_or(mask,regv_h(value),adr); + printf("\tmovl 0(%%esp),%s\n",register_name(adr,0)); + printf("\t%s %s,4(%s)\n",move(0), + l_edx(value), register_name(adr,0)); + } + if (bitpos<32) { + if (!push) { printf("\tpushl %s\n",register_name(adr,0)); push=1;} + /* make and-mask lower */ + printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0), + register_name(adr,0)); + mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos); + make_mask_and_or(mask,regv_l(value),adr); + printf("\tpopl %s\n",register_name(adr,0)); push=0; + printf("\t%s %s,(%s)\n",move(0), + l_eax(value), register_name(adr,0)); + } + if (push) printf("\taddl %%sp,$4\n"); +#endif + } else { + use_int(adr); + use_int(value); + printf("\tpushl %s\n",register_name(adr,0)); + printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0), + register_name(adr,0)); + /* shift left */ + if (bitpos) + oprtc(LSHIFT,value,list2(CONST,bitpos)); + /* make and-mask */ + mask = make_mask(32-bitpos-bitsize,31-bitpos); + make_mask_and_or(mask,value,adr); + printf("\tpopl %s\n",register_name(adr,0)); + code_assign(adr,size==4?0:size,value); + } + if (use) { + code_bit_field(type,adr,USE_CREG); + } +} + + +static void +make_mask_and_or_const(int mask,int reg,int c) +{ + int a; +// printf("## mask 0x%08x ~0x%08x\n",mask,~mask); + a = ~mask|c; + if (a!=-1) { + /* do conjunction */ + if (reg<MAX_DATA_REG && ((a& ~0xffff)==~0xffff)) { + if ((a& ~0xff)==~0xff) + printf("\tandb $%d,%s\n",a&0xff,register_name(reg,1)); + else + printf("\tandw $%d,%s\n",a&0xffff,register_name(reg,2)); + } else + printf("\tandl $%d,%s\n",a,register_name(reg,0)); + } + /* make or-mask */ + c = mask&c; + if (c!=0) { + /* do disjunction */ + if (reg<MAX_DATA_REG && (!(c& ~0xffff))) { + if (!(c& ~0xff)) + printf("\torb $%d,%s\n",c&0xff,register_name(reg,1)); + else + printf("\torw $%d,%s\n",c&0xffff,register_name(reg,2)); + } else + printf("\torl $%d,%s\n",c,register_name(reg,0)); + } +} + +extern void +code_bit_replace_const(int value,int adr,int type) +{ + int sign,bitsz,l,align; + int bitpos,bitsize,size; + int mask = 0; + int c,lvalue; +#if LONGLONG_CODE + long long lc; +#endif + set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l); + size = bitsz/8; +// printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); + use_int(adr); + if (l) { +#if LONGLONG_CODE + lvalue = get_register(); + /* shift left */ + lc = lcadr(value); + lc <<= bitpos; + + if (bitpos+bitsize>=32) { + printf("\t%s %d(%s),%s\n",cload(sign,size),4,register_name(adr,0), + register_name(lvalue,0)); + /* make and-mask upper */ + mask = make_mask(64-bitpos-bitsize,bitpos>=32?63-bitpos:31); + make_mask_and_or_const(mask,lvalue,(int)(lc>>32)); + printf("\t%s %s,4(%s)\n",move(0),register_name(lvalue,0), + register_name(adr,0)); + } + if (bitpos<32) { + printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0), + register_name(lvalue,0)); + /* make and-mask lower */ + mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos); + make_mask_and_or_const(mask,lvalue,(int)(lc)); + printf("\t%s %s,(%s)\n",move(0), + register_name(lvalue,0),register_name(adr,0)); + } + free_register(lvalue); +#endif + } else { + lvalue = get_register(); + printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0), + register_name(lvalue,0)); + /* shift left */ + c = cadr(value); + c <<= bitpos; + /* make and-mask */ + mask = make_mask(32-bitpos-bitsize,31-bitpos); + make_mask_and_or_const(mask,lvalue,c); + code_assign(adr,size==4?0:size,lvalue); + free_register(lvalue); + } + if (use) + code_bit_field(type,adr,USE_CREG); +} + +#endif + +int +not_simple_p(int e3) +{ + switch(e3) { + case FUNCTION: case CONV: case STASS: case ALLOCA: + case LDIV: case LUDIV: case LMOD: case LUMOD: + case LMUL: case LUMUL: + case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT: + case DDIV: case DADD: case DSUB: case DMUL: case DMINUS: + case DPOSTINC : case DPREINC : case DASSOP : + case DOP+LT : case DOP+LE : case DOP+GT : case DOP+GE : + case DOP+EQ : case DOP+NEQ: + case RBIT_FIELD: case BASS: case BASSOP: case LCALL: + case INLINE: + return 1; + } + return 0; +} + +extern int +code_arg_alignment(int args,NMTBL *n, int type0,int sz) +{ + return code_arg_alignment0(args,n, type0,sz); +} + + +extern int +code_lvar_alignment(int args,NMTBL *n, int type0,int sz) +{ + return code_lvar_alignment0(args,n, type0,sz); +} + + +/* end */
--- a/mc-parse.c Fri Oct 29 16:13:47 2010 +0900 +++ b/mc-parse.c Fri Oct 29 16:14:00 2010 +0900 @@ -118,6 +118,7 @@ int mode,stmode,ctmode,inmode; // mode, storage mode, constant mode, inline int decl_str_init; // delayed local struct initialize int parse; // parse tree list for inline +int lp64; // LP64 mode (long = (int *) = 8) NMTBL *local_static_list,*global_list; // list of static, global variable @@ -1077,40 +1078,42 @@ t=sdecl(sym); break; case SIGNED: - t = INT; + t = INT; // default if(getsym(0)==INT) getsym(0); else if (sym==CHAR) { getsym(0); t = CHAR; } else if (sym==SHORT) { t = SHORT; - if(getsym(0)==INT) getsym(0); - } else if (sym==LONG) { + if(getsym(0)==INT) getsym(0); // signed short int + } else if (sym==LONG) { // signed long getsym(0); - t = INT; - if(sym==LONG) { + t = lp64?LONGLONG:INT; + if(sym==LONG) { // signed long long if(getsym(0)==INT) getsym(0); t=LONGLONG; - } else if(sym==INT) { + } else if(sym==INT) { // signed long int getsym(0); - t=INT; + t = lp64?LONGLONG:INT; } } break; case UNSIGNED: t = UNSIGNED; - if(getsym(0)==INT) getsym(0); - else if (sym==CHAR) { getsym(0); t = UCHAR; } + if(getsym(0)==INT) { + t = lp64?ULONGLONG:UNSIGNED; + getsym(0); + } else if (sym==CHAR) { getsym(0); t = UCHAR; } else if (sym==SHORT) { t = USHORT; if(getsym(0)==INT) getsym(0); } else if (sym==LONG) { getsym(0); - t = UNSIGNED; + t = lp64?ULONGLONG:UNSIGNED; if(sym==LONG) { if(getsym(0)==INT) getsym(0); t=ULONGLONG; - } else if(sym==INT) { + } else if(sym==INT) { // unsigend long int getsym(0); - t=UNSIGNED; + t = lp64?ULONGLONG:UNSIGNED; } } break; @@ -1122,7 +1125,7 @@ } break; case LONG: - t=INT; + t = lp64?LONGLONG:INT; getsym(0); if(sym==LONG) { getsym(0); @@ -1137,8 +1140,8 @@ t=DOUBLE; } else if(sym==INT) { getsym(0); } else if(sym==UNSIGNED) { - if(getsym(0)==INT) getsym(0); - t=UNSIGNED; + if(getsym(0)==INT) getsym(0); // long unsigend int + t = lp64?ULONGLONG:UNSIGNED; } // break; case TYPEOF:
--- a/mc.h Fri Oct 29 16:13:47 2010 +0900 +++ b/mc.h Fri Oct 29 16:14:00 2010 +0900 @@ -592,12 +592,12 @@ extern void print_expr(int e, FILE *vout); -#if 1 -extern int heapsize; -#define CHECK_HEAP(b) ({int _k=(int)(b);if(_k>heapsize||_k<=0)error(-1);_k;}) -#else +// #if 1 +//extern int heapsize; +// #define CHECK_HEAP1(b) ({int _k=(int)(b);if(_k>heapsize||_k<=0)error(-1);_k;}) +//#else #define CHECK_HEAP(b) (b) -#endif +//#endif #define car(e) (heap[(int)(CHECK_HEAP(e))])
--- a/test/code-gen.c Fri Oct 29 16:13:47 2010 +0900 +++ b/test/code-gen.c Fri Oct 29 16:14:00 2010 +0900 @@ -25,15 +25,15 @@ unsigned long long ll; } u; u.ll = 0; - printf("sizeof(char)=%d\n",sizeof(char)); - printf("sizeof(short)=%d\n",sizeof(short)); - printf("sizeof(int)=%d\n",sizeof(int)); - printf("sizeof(long)=%d\n",sizeof(long)); - printf("sizeof(int*)=%d\n",sizeof(int*)); - printf("sizeof(long long)=%d\n",sizeof(long long)); - printf("sizeof(float)=%d\n",sizeof(float)); - printf("sizeof(double)=%d\n",sizeof(double)); - printf("sizeof(long double)=%d\n",sizeof(long double)); + printf("sizeof(char)=%ld\n",sizeof(char)); + printf("sizeof(short)=%ld\n",sizeof(short)); + printf("sizeof(int)=%ld\n",sizeof(int)); + printf("sizeof(long)=%ld\n",sizeof(long)); + printf("sizeof(int*)=%ld\n",sizeof(int*)); + printf("sizeof(long long)=%ld\n",sizeof(long long)); + printf("sizeof(float)=%ld\n",sizeof(float)); + printf("sizeof(double)=%ld\n",sizeof(double)); + printf("sizeof(long double)=%ld\n",sizeof(long double)); u.s = 0x0123; printf("#0025:endian s : %02x %02x\n",u.a[0],u.a[1]); u.i = 0x01234567; @@ -178,10 +178,10 @@ INLINE void code_fname() { - int i,j,k; - i = (int)code_fname; - j = (int)code_register; - k = (int)exit; + long i,j,k; + i = (long)code_fname; + j = (long)code_register; + k = (long)exit; printf("#0162:code_fname %d %d\n",i==j,i==k); } @@ -746,11 +746,11 @@ i1 = 1; i2 = -2; s1 = -1; s2 = -3; us1 = 65535; us2 = 65535; c1 = -1; c2 = -3; uc1 = 200; uc2 = 202; - i1 && printf("#0715:code_bool local 1\n"); - s1 && printf("#0716:code_bool local 2\n"); - us1 && printf("#0717:code_bool local 3\n"); - c1 && printf("#0718:code_bool local 4\n"); - uc1 && printf("#0719:code_bool local 5\n"); + if(i1 ) printf("#0715:code_bool local 1\n"); + if(s1 ) printf("#0716:code_bool local 2\n"); + if(us1 ) printf("#0717:code_bool local 3\n"); + if(c1 ) printf("#0718:code_bool local 4\n"); + if(uc1 ) printf("#0719:code_bool local 5\n"); } INLINE void @@ -759,11 +759,11 @@ i1 = 1; i2 = -2; s1 = -1; s2 = -3; us1 = 65535; us2 = 65535; c1 = -1; c2 = -3; uc1 = 200; uc2 = 202; - i1 && printf("#0728:code_bool global 1\n"); - s1 && printf("#0729:code_bool global 2\n"); - us1 && printf("#0730:code_bool global 3\n"); - c1 && printf("#0731:code_bool global 4\n"); - uc1 && printf("#0732:code_bool global 5\n"); + if(i1 ) printf("#0728:code_bool global 1\n"); + if(s1 ) printf("#0729:code_bool global 2\n"); + if(us1 ) printf("#0730:code_bool global 3\n"); + if(c1 ) printf("#0731:code_bool global 4\n"); + if(uc1 ) printf("#0732:code_bool global 5\n"); } INLINE void @@ -778,11 +778,11 @@ i1 = 1; i2 = -2; s1 = -1; s2 = -3; us1 = 65535; us2 = 65535; c1 = -1; c2 = -3; uc1 = 200; uc2 = 202; - i1 && printf("#0747:code_bool register 1\n"); - s1 && printf("#0748:code_bool register 2\n"); - us1 && printf("#0749:code_bool register 3\n"); - c1 && printf("#0750:code_bool register 4\n"); - uc1 && printf("#0751:code_bool register 5\n"); + if(i1 ) printf("#0747:code_bool register 1\n"); + if(s1 ) printf("#0748:code_bool register 2\n"); + if(us1 ) printf("#0749:code_bool register 3\n"); + if(c1 ) printf("#0750:code_bool register 4\n"); + if(uc1 ) printf("#0751:code_bool register 5\n"); } @@ -1539,8 +1539,8 @@ register double d0,d1; f0 = 0.0; f1 = 0.2; d0 = 10; d1 = 10e10; - f0 && printf("#1498:code_bool register 6\n"); - d0 && printf("#1499:code_bool register 7\n"); + if (f0 ) printf("#1498:code_bool register 6\n"); + if (d0 ) printf("#1499:code_bool register 7\n"); } @@ -1746,8 +1746,8 @@ { f0 = 0.0; f1 = 0.2; d0 = 10; d1 = 10e10; - f0 && printf("#1705:code_bool global 6\n"); - d0 && printf("#1706:code_bool global 7\n"); + if(f0 ) printf("#1705:code_bool global 6\n"); + if(d0 ) printf("#1706:code_bool global 7\n"); } @@ -1759,8 +1759,8 @@ double d0,d1; f0 = 0.0; f1 = 0.2; d0 = 10; d1 = 10e10; - f0 && printf("#1718:code_bool local 6\n"); - d0 && printf("#1719:code_bool local 7\n"); + if(f0 ) printf("#1718:code_bool local 6\n"); + if(d0 ) printf("#1719:code_bool local 7\n"); } // dtosop(int op,int e1) @@ -2123,8 +2123,8 @@ l1 = 123123123LL; ul0 = 123123123LL; ul1 = 123123123LL; - l0 && printf("#2082:code_bool register 8\n"); - ul0 && printf("#2083:code_bool register 9\n"); + if(l0 ) printf("#2082:code_bool register 8\n"); + if(ul0 ) printf("#2083:code_bool register 9\n"); } // code_cmp_lrgvar(int e1,int e2) @@ -2135,8 +2135,8 @@ l1 = 123123123LL; ul0 = 123123123LL; ul1 = 123123123LL; - l0 && printf("#2094:code_bool global 8\n"); - ul0 && printf("#2095:code_bool global 9\n"); + if(l0 ) printf("#2094:code_bool global 8\n"); + if(ul0 ) printf("#2095:code_bool global 9\n"); } // code_cmp_lrlvar(int e1,int e2) INLINE void @@ -2148,8 +2148,8 @@ l1 = 123123123LL; ul0 = 123123123LL; ul1 = 123123123LL; - l0 && printf("#2107:code_bool local 8\n"); - ul0 && printf("#2108:code_bool local 9\n"); + if(l0 ) printf("#2107:code_bool local 8\n"); + if(ul0 ) printf("#2108:code_bool local 9\n"); } // code_lassign(int e1,int e2)