diff --git a/examples/asm/elmer/ipl-scd/ipl-scd.asm b/examples/asm/elmer/ipl-scd/ipl-scd.asm index 48bc18b9..ce232da4 100644 --- a/examples/asm/elmer/ipl-scd/ipl-scd.asm +++ b/examples/asm/elmer/ipl-scd/ipl-scd.asm @@ -124,6 +124,26 @@ iso_128mb = iso_dirhi ; index # of 1st beyond 128MB .mlist + +; *************************************************************************** +; *************************************************************************** +; +; "pcengine.inc" only defines these for a CD/SCD/ACD build so ... +; + + .ifndef cd_read +cd_read = $00:E009, FUNC +ex_getver = $00:E05A, FUNC +ex_scrsiz = $00:E069, FUNC +ex_scrmod = $00:E06F, FUNC +ex_vsync = $00:E07B, FUNC +ex_bgon = $00:E08A, FUNC +ex_dspoff = $00:E099, FUNC +ex_memopen = $00:E0DE, FUNC + .endif + + + ; *************************************************************************** ; *************************************************************************** ; diff --git a/examples/hucc/shmup/shmup.c b/examples/hucc/shmup/shmup.c index ad995918..1c661679 100644 --- a/examples/hucc/shmup/shmup.c +++ b/examples/hucc/shmup/shmup.c @@ -13,6 +13,12 @@ #incspr(explosion,"explosion.pcx",0,0,2,16) #incpal(explosionpal,"explosion.pcx") +const unsigned char * aSpriteDataAddr[] = { + &bonk, &bullet, &ship, &explosion }; + +const unsigned char aSpriteDataBank[] = { + ^bonk, ^bullet, ^ship, ^explosion }; + #incchr(scene_chr,"scene.png") #incpal(scene_pal,"scene.png") #incbat(scene_bat,"scene.png",0x1000,32,28) @@ -196,7 +202,17 @@ void main(void) load_palette(18,shippal,1); load_palette(19,explosionpal,1); + // you can either load vram using the label sgx_load_vram(0x5000,bonk,0x400); + + // or by using using the bank and address + set_far_base(aSpriteDataBank[0],aSpriteDataAddr[0]); + sgx_far_load_vram(0x5000,0x400); + + // or by using using the bank and address with an offset + set_far_offset(0,aSpriteDataBank[0],aSpriteDataAddr[0]); + sgx_far_load_vram(0x5000,0x400); + sgx_load_vram(0x5400,bullet,0x40); sgx_load_vram(0x5500,ship,0x400); sgx_load_vram(0x5900,explosion,0x800); diff --git a/include/hucc/hucc-baselib.asm b/include/hucc/hucc-baselib.asm index 328ed5e8..7f52f900 100644 --- a/include/hucc/hucc-baselib.asm +++ b/include/hucc/hucc-baselib.asm @@ -3,7 +3,7 @@ ; ; hucc-baselib.asm ; -; Basic library functions provided as macros. +; Basic library functions provided (mostly) as macros. ; ; Copyright John Brandwood 2024. ; @@ -68,6 +68,36 @@ _exit.1: tax ; Put the return code into X. +; *************************************************************************** +; *************************************************************************** +; +; void __fastcall __xsafe __nop set_far_base( unsigned char data_bank<_bp_bank>, unsigned char *data_addr<_bp> ); +; void __fastcall __xsafe set_far_offset( unsigned int offset<_bp>, unsigned char data_bank<_bp_bank>, unsigned char *data_addr ); + +_set_far_offset.3: + clc + adc.l <_bp + sta.l <_bp + tya + and #$1F + adc.h <_bp + tay + and #$1F + ora #$60 + sta.h <_bp + tya + ror a + lsr a + lsr a + lsr a + lsr a + clc + adc <_bp_bank + sta <_bp_bank + rts + + + ; *************************************************************************** ; *************************************************************************** ; diff --git a/include/hucc/hucc-baselib.h b/include/hucc/hucc-baselib.h index 822508a7..60b94589 100644 --- a/include/hucc/hucc-baselib.h +++ b/include/hucc/hucc-baselib.h @@ -85,6 +85,9 @@ extern unsigned char dh; #asmdef HUCC_USES_BASELIB 1 +extern void __fastcall __xsafe __nop set_far_base( unsigned char data_bank<_bp_bank>, unsigned char *data_addr<_bp> ); +extern void __fastcall __xsafe set_far_offset( unsigned int offset<_bp>, unsigned char data_bank<_bp_bank>, unsigned char *data_addr ); + extern unsigned char __fastcall __xsafe __macro sgx_detect( void ); extern unsigned char __fastcall __xsafe __macro ac_exists( void ); diff --git a/include/hucc/hucc-codegen.asm b/include/hucc/hucc-codegen.asm index 1b7778a6..baaa5e8f 100644 --- a/include/hucc/hucc-codegen.asm +++ b/include/hucc/hucc-codegen.asm @@ -520,16 +520,26 @@ __switch.ur .macro jmp do_switchb .endm +; ************** +; the start of a "default" statement + +__default .macro + plx + .endm + ; ************** ; the start of a "case" statement __case .macro + plx .endm ; ************** ; the end of the previous "case" statement if it drops through +; turns next __case "plx" into an "ora" __endcase .macro + db $09 .endm ; ************** @@ -4239,7 +4249,9 @@ smodw: sta.l .BAT_SIZE ; Size of BAT in words. - sta <_bl - - call clear_vram_vdc ; Clear VRAM. - .if SUPPORT_SGX - call clear_vram_sgx - .endif - - lda #<.mode_352x224 ; Disable BKG & SPR layers but - sta.l <_bp ; enable RCR & VBLANK IRQ. - lda #>.mode_352x224 - sta.h <_bp - - .if SUPPORT_SGX - call sgx_detect ; Are we really on an SGX? - bcc !+ - ldy #^.mode_352x224 ; Set SGX 1st, with no VBL. - call set_mode_sgx - - ldy #VDC_MWR_64x32 >> 4 ; HuCC sets up various vars - call screen_size_sgx ; related to the BAT size. - .endif -!: ldy #^.mode_352x224 ; Set VDC 2nd, VBL allowed. - call set_mode_vdc - - lda #VDC_MWR_64x32 >> 4 ; HuCC sets up various vars - sta <_al ; related to the BAT size. - call screen_size_vdc - - .if SUPPORT_SGX - bit SGX_SR ; Purge any overdue RCR. - .endif - bit VDC_SR ; Purge any overdue RCR/VBL. - plp ; Restore interrupts. - - call wait_vsync ; Wait for the next VBLANK. - - plx ; Restore X (aka __sp). - - leave ; All done, phew! - - ; A standard 352x224 screen with overscan. - -.mode_352x224: db $80 ; VCE Control Register. - db VCE_CR_7MHz + XRES_SOFT ; Video Clock + Artifact Reduction - - db VDC_MWR ; Memory-access Width Register - dw VDC_MWR_64x32 + VDC_MWR_1CYCLE - db VDC_HSR ; Horizontal Sync Register - dw VDC_HSR_352 - db VDC_HDR ; Horizontal Display Register - dw VDC_HDR_352 - db VDC_VPR ; Vertical Sync Register - dw VDC_VPR_224 - db VDC_VDW ; Vertical Display Register - dw VDC_VDW_224 - db VDC_VCR ; Vertical Display END position Register - dw VDC_VCR_224 - db VDC_DCR ; DMA Control Register - dw $0010 ; Enable automatic VRAM->SATB - db VDC_DVSSR ; VRAM->SATB address $7F00 - dw .SAT_ADDR - db VDC_BXR ; Background X-Scroll Register - dw $0000 - db VDC_BYR ; Background Y-Scroll Register - dw $0000 - db VDC_RCR ; Raster Counter Register - dw $0000 ; Never occurs! - db VDC_CR ; Control Register - dw $00CC ; Enable VSYNC & RCR IRQ, BG & SPR - db 0 - - .endp - - - -; *************************************************************************** -; *************************************************************************** -; -; void __fastcall __xsafe set_496x224( void ); - -_set_496x224 .proc - -.BAT_SIZE = 64 * 32 -.CHR_0x20 = .BAT_SIZE / 16 ; 1st tile # after the BAT. -.SAT_ADDR = $7F00 ; SAT takes 16 tiles of VRAM. - - phx ; Preserve X (aka __sp). - - php ; Disable interrupts. - sei - - call clear_vce ; Clear all palettes. - - lda.l #.CHR_0x20 ; Tile # of ' ' CHR. - sta.l <_ax - lda.h #.CHR_0x20 - sta.h <_ax - - lda #>.BAT_SIZE ; Size of BAT in words. - sta <_bl - - call clear_vram_vdc ; Clear VRAM. - .if SUPPORT_SGX - call clear_vram_sgx - .endif - - lda #<.mode_496x224 ; Disable BKG & SPR layers but - sta.l <_bp ; enable RCR & VBLANK IRQ. - lda #>.mode_496x224 - sta.h <_bp - - .if SUPPORT_SGX - call sgx_detect ; Are we really on an SGX? - bcc !+ - ldy #^.mode_496x224 ; Set SGX 1st, with no VBL. - call set_mode_sgx - - ldy #VDC_MWR_64x32 >> 4 ; HuCC sets up various vars - call screen_size_sgx ; related to the BAT size. - .endif -!: ldy #^.mode_496x224 ; Set VDC 2nd, VBL allowed. - call set_mode_vdc - - lda #VDC_MWR_64x32 >> 4 ; HuCC sets up various vars - sta <_al ; related to the BAT size. - call screen_size_vdc - - .if SUPPORT_SGX - bit SGX_SR ; Purge any overdue RCR. - .endif - bit VDC_SR ; Purge any overdue RCR/VBL. - plp ; Restore interrupts. - - call wait_vsync ; Wait for the next VBLANK. - - plx ; Restore X (aka __sp). - - leave ; All done, phew! - - ; A standard 496x224 screen with overscan. - -.mode_496x224: db $80 ; VCE Control Register. - db VCE_CR_10MHz + XRES_SOFT; Video Clock + Artifact Reduction - - db VDC_MWR ; Memory-access Width Register - dw VDC_MWR_64x32 + VDC_MWR_2CYCLE - db VDC_HSR ; Horizontal Sync Register - dw VDC_HSR_496 - db VDC_HDR ; Horizontal Display Register - dw VDC_HDR_496 - db VDC_VPR ; Vertical Sync Register - dw VDC_VPR_224 - db VDC_VDW ; Vertical Display Register - dw VDC_VDW_224 - db VDC_VCR ; Vertical Display END position Register - dw VDC_VCR_224 - db VDC_DCR ; DMA Control Register - dw $0010 ; Enable automatic VRAM->SATB - db VDC_DVSSR ; VRAM->SATB address $7F00 - dw .SAT_ADDR - db VDC_BXR ; Background X-Scroll Register - dw $0000 - db VDC_BYR ; Background Y-Scroll Register - dw $0000 - db VDC_RCR ; Raster Counter Register - dw $0000 ; Never occurs! - db VDC_CR ; Control Register - dw $00CC ; Enable VSYNC & RCR IRQ, BG & SPR - db 0 - - .endp - - - ; *************************************************************************** ; *************************************************************************** ; @@ -652,9 +455,13 @@ set_tile_base: sty <__temp ; Set TILE base = (VRAM / 16). ; *************************************************************************** ; ; void __fastcall __xsafe set_tile_data( unsigned char *tile_ex<_di> ); +; ; void __fastcall __xsafe __nop set_tile_data( unsigned char far *map, unsigned char nb_tile, unsigned char far *ptable, unsigned char type ); ; void __fastcall __xsafe __nop sgx_set_tile_data( unsigned char far *map, unsigned char nb_tile, unsigned char far *ptable, unsigned char type ); ; +; void __fastcall __xsafe __nop set_far_tile_data( unsigned char tile_bank, unsigned char *tile_addr, unsigned char num_tiles, unsigned char palette_table_bank, unsigned char *palette_table_addr, unsigned char tile_type ); +; void __fastcall __xsafe __nop sgx_set_far_tile_data( unsigned char tile_bank, unsigned char *tile_addr, unsigned char num_tiles, unsigned char palette_table_bank, unsigned char *palette_table_addr, unsigned char tile_type ); +; ; tile, tile base index ; nb_tile, number of tile ; ptable, tile palette table address @@ -767,6 +574,9 @@ load_vram_group .procgroup ; These routines share code! ; void __fastcall __xsafe load_vram( unsigned int vram<_di>, unsigned char __far *data<_bp_bank:_bp>, unsigned int num_words<_ax> ); ; void __fastcall __xsafe sgx_load_vram( unsigned int vram<_di>, unsigned char __far *data<_bp_bank:_bp>, unsigned int num_words<_ax> ); ; +; void __fastcall __xsafe far_load_vram( unsigned int vram<_di>, unsigned int num_words<_ax> ); +; void __fastcall __xsafe sgx_far_load_vram( unsigned int vram<_di>, unsigned int num_words<_ax> ); +; ; load_vram_sgx - copy a block of memory to VRAM ; load_vram_vdc - copy a block of memory to VRAM ; @@ -783,6 +593,8 @@ VRAM_XFER_SIZE = 16 .if SUPPORT_SGX .proc _sgx_load_vram.3 + .alias _sgx_far_load_vram.2 = _sgx_load_vram.3 + ldy #SGX_VDC_OFFSET ; Offset to SGX VDC. db $F0 ; Turn "cly" into a "beq". @@ -792,6 +604,7 @@ VRAM_XFER_SIZE = 16 .endif .proc _load_vram.3 + .alias _far_load_vram.2 = _load_vram.3 cly ; Offset to PCE VDC. @@ -897,6 +710,9 @@ huc_load_vram: tma3 ; void __fastcall __xsafe load_bat( unsigned int vram<_di>, unsigned char __far *data<_bp_bank:_bp>, unsigned char tiles_w<_al>, unsigned char tiles_h<_ah> ); ; void __fastcall __xsafe sgx_load_bat( unsigned int vram<_di>, unsigned char __far *data<_bp_bank:_bp>, unsigned char tiles_w<_al>, unsigned char tiles_h<_ah> ); ; +; void __fastcall __xsafe far_load_bat( unsigned int vram<_di>, unsigned char tiles_w<_al>, unsigned char tiles_h<_ah> ); +; void __fastcall __xsafe sgx_far_load_bat( unsigned int vram<_di>, unsigned char tiles_w<_al>, unsigned char tiles_h<_ah> ); +; ; load_bat_sgx - transfer a BAT to VRAM ; load_bat_vdc - transfer a BAT to VRAM ; @@ -919,6 +735,7 @@ load_bat_group .procgroup ; These routines share code! .if SUPPORT_SGX .proc _sgx_load_bat.4 + .alias _sgx_far_load_bat.3 = _sgx_load_bat.4 ldy #SGX_VDC_OFFSET ; Offset to SGX VDC. db $F0 ; Turn "cly" into a "beq". @@ -928,6 +745,7 @@ load_bat_group .procgroup ; These routines share code! .endif .proc _load_bat.4 + .alias _far_load_bat.3 = _load_bat.4 cly ; Offset to PCE VDC. @@ -984,8 +802,11 @@ load_bat_group .procgroup ; These routines share code! ; *************************************************************************** ; ; void __fastcall __xsafe load_palette( unsigned char palette<_al>, unsigned char __far *data<_bp_bank:_bp>, unsigned char num_palettes<_ah> ); +; +; void __fastcall __xsafe far_load_palette( unsigned char palette<_al>, unsigned char num_palettes<_ah> ); .proc _load_palette.3 + .alias _far_load_palette.2 = _load_palette.3 ldy color_queue_w ; Get the queue's write index. @@ -1147,6 +968,8 @@ _set_font_pal: ; ************** ; void __fastcall __xsafe load_font( char far *font<_bp_bank:_bp>, unsigned char count<_al> ); ; void __fastcall __xsafe load_font( char far *font<_bp_bank:_bp>, unsigned char count<_al>, unsigned int vram ); +; +; void __fastcall __xsafe far_load_font( unsigned char count<_al>, unsigned int vram ); _load_font.2: ldy vdc_bat_limit ; BAT limit mask hi-byte. iny @@ -1170,6 +993,8 @@ _load_font.3: sta.l <_di ; Load the font directly sta <__al jmp _load_vram.3 ; This is __xsafe! + .alias _far_load_font.2 = _load_font.3 + ; ************** diff --git a/include/hucc/hucc-gfx.h b/include/hucc/hucc-gfx.h index 7ae72a57..75db4f91 100644 --- a/include/hucc/hucc-gfx.h +++ b/include/hucc/hucc-gfx.h @@ -83,6 +83,9 @@ extern void __fastcall sgx_set_tile_address( unsigned int vram ); extern void __fastcall __xsafe __nop set_tile_data( unsigned char __far *tiles, unsigned char num_tiles, unsigned char __far *palette_table, unsigned char tile_type ); extern void __fastcall __xsafe __nop sgx_set_tile_data( unsigned char __far *tiles, unsigned char num_tiles, unsigned char __far *palette_table, unsigned char tile_type ); +extern void __fastcall __xsafe __nop set_far_tile_data( unsigned char tile_bank, unsigned char *tile_addr, unsigned char num_tiles, unsigned char palette_table_bank, unsigned char *palette_table_addr, unsigned char tile_type ); +extern void __fastcall __xsafe __nop sgx_set_far_tile_data( unsigned char tile_bank, unsigned char *tile_addr, unsigned char num_tiles, unsigned char palette_table_bank, unsigned char *palette_table_addr, unsigned char tile_type ); + extern void __fastcall __xsafe load_vram( unsigned int vram<_di>, unsigned char __far *data<_bp_bank:_bp>, unsigned int num_words<_ax> ); extern void __fastcall __xsafe sgx_load_vram( unsigned int vram<_di>, unsigned char __far *data<_bp_bank:_bp>, unsigned int num_words<_ax> ); @@ -115,12 +118,22 @@ extern void __fastcall cls( unsigned int tile ); /* NOT __xsafe! */ extern void __fastcall __xsafe disp_on( void ); extern void __fastcall __xsafe disp_off( void ); -extern void __fastcall __xsafe set_tile_data( unsigned char *tile_ex<_di> ); +// extern void __fastcall __xsafe __nop set_far_base( unsigned char data_bank<_bp_bank>, unsigned char *data_addr<_bp> ); +// extern void __fastcall __xsafe set_far_offset( unsigned int offset<_bp>, unsigned char data_bank<_bp_bank>, unsigned char *data_addr ); -extern void __fastcall __xsafe load_background( unsigned char __far *tiles<_bp_bank:_bp>, unsigned char __far *palettes<__fbank:__fptr>, unsigned char __far *bat<_cl:_bx>, unsigned char w<_dl>, unsigned char h<_dh> ); +extern void __fastcall __xsafe far_load_vram( unsigned int vram<_di>, unsigned int num_words<_ax> ); +extern void __fastcall __xsafe sgx_far_load_vram( unsigned int vram<_di>, unsigned int num_words<_ax> ); + +extern void __fastcall __xsafe far_load_bat( unsigned int vram<_di>, unsigned char tiles_w<_al>, unsigned char tiles_h<_ah> ); +extern void __fastcall __xsafe sgx_far_load_bat( unsigned int vram<_di>, unsigned char tiles_w<_al>, unsigned char tiles_h<_ah> ); + +extern void __fastcall __xsafe far_load_palette( unsigned char palette<_al>, unsigned char num_palettes<_ah> ); +extern void __fastcall __xsafe far_load_font( unsigned char count<_al>, unsigned int vram ); // Deprecated functions ... +extern void __fastcall __xsafe load_background( unsigned char __far *tiles<_bp_bank:_bp>, unsigned char __far *palettes<__fbank:__fptr>, unsigned char __far *bat<_cl:_bx>, unsigned char w<_dl>, unsigned char h<_dh> ); +extern void __fastcall __xsafe set_tile_data( unsigned char *tile_ex<_di> ); extern void __fastcall __xsafe __macro set_bgpal( unsigned char palette<_al>, unsigned char __far *data<_bp_bank:_bp> ); extern void __fastcall __xsafe __macro set_bgpal( unsigned char palette<_al>, unsigned char __far *data<_bp_bank:_bp>, unsigned int num_palettes<_ah> ); extern void __fastcall __xsafe __macro set_sprpal( unsigned char palette<_al>, unsigned char __far *data<_bp_bank:_bp> ); diff --git a/include/hucc/hucc-old-map.h b/include/hucc/hucc-old-map.h index 8e60704d..a01152b7 100644 --- a/include/hucc/hucc-old-map.h +++ b/include/hucc/hucc-old-map.h @@ -29,6 +29,9 @@ extern void __fastcall __xsafe __nop set_map_data( unsigned char __far *map, unsigned char w, unsigned char h ); extern void __fastcall __xsafe __nop sgx_set_map_data( unsigned char __far *map, unsigned char w, unsigned char h ); +extern void __fastcall __xsafe __nop set_far_map_data( unsigned char map_bank, unsigned char *map_addr, unsigned char w, unsigned char h ); +extern void __fastcall __xsafe __nop sgx_set_far_map_data( unsigned char map_bank, unsigned char *map_addr, unsigned char w, unsigned char h ); + extern void __fastcall __xsafe load_map( unsigned char bat_x<_al>, unsigned char bat_y<_ah>, int map_x<_bx>, int map_y<_dx>, unsigned char tiles_w<_cl>, unsigned char tiles_h<_ch> ); extern void __fastcall __xsafe sgx_load_map( unsigned char bat_x<_al>, unsigned char bat_y<_ah>, int map_x<_bx>, int map_y<_dx>, unsigned char tiles_w<_cl>, unsigned char tiles_h<_ch> ); diff --git a/include/hucc/pcengine.inc b/include/hucc/pcengine.inc index c43ea876..6832e109 100644 --- a/include/hucc/pcengine.inc +++ b/include/hucc/pcengine.inc @@ -28,17 +28,17 @@ ; and assumes that equates in the $00xx region are zero-page. ; -VDC_SR = $FF:0200 ; Status Register -VDC_AR = $FF:0200 ; Address Register -VDC_DL = $FF:0202 ; Data (Read/Write) Low -VDC_DH = $FF:0203 ; Data (Read/Write) High +VDC_SR = $FF:0200, 1 ; Status Register +VDC_AR = $FF:0200, 1 ; Address Register +VDC_DL = $FF:0202, 1 ; Data (Read/Write) Low +VDC_DH = $FF:0203, 1 ; Data (Read/Write) High -SGX_SR = $FF:0210 ; Status Register -SGX_AR = $FF:0210 ; Address Register -SGX_DL = $FF:0212 ; Data (Read/Write) Low -SGX_DH = $FF:0213 ; Data (Read/Write) High +SGX_SR = $FF:0210, 1 ; Status Register +SGX_AR = $FF:0210, 1 ; Address Register +SGX_DL = $FF:0212, 1 ; Data (Read/Write) Low +SGX_DH = $FF:0213, 1 ; Data (Read/Write) High -SGX_DETECT = $FF:0218 ; $FF if SGX or VDC_SR mirror (i.e. < $80) +SGX_DETECT = $FF:0218, 2 ; $FF if SGX or VDC_SR mirror (i.e. < $80) VDC_MAWR = 0 ; Memory Address Write VDC_MARR = 1 ; Memory Address Read @@ -67,11 +67,11 @@ VDC_DVSSR = 19 ; VRAM-SATB Block Transfer Source ; HuC6202 - Video Priority Controller (SGX-only) ; -VPC_CR = $FF:0208 ; Defaults to $1111 -VPC_WINDOW1 = $FF:020A ; Defaults to $0000 -VPC_WINDOW2 = $FF:020C ; Defaults to $0000 -VPC_STMODE = $FF:020E ; Defaults to $00=VDC ($01=SGX) -VPC_UNKNOWN = $FF:020F ; Defaults to $00 +VPC_CR = $FF:0208, 2 ; Defaults to $1111 +VPC_WINDOW1 = $FF:020A, 2 ; Defaults to $0000 +VPC_WINDOW2 = $FF:020C, 2 ; Defaults to $0000 +VPC_STMODE = $FF:020E, 1 ; Defaults to $00=VDC ($01=SGX) +VPC_UNKNOWN = $FF:020F, 1 ; Defaults to $00 @@ -82,10 +82,10 @@ VPC_UNKNOWN = $FF:020F ; Defaults to $00 ; Palette Data is 0000000gggrrrbbb ; -VCE_CR = $FF:0400 ; Control Register -VCE_CTA = $FF:0402 ; Color Table Address -VCE_CTW = $FF:0404 ; Color Table Data Write -VCE_CTR = $FF:0404 ; Color Table Data Read +VCE_CR = $FF:0400, 2 ; Control Register +VCE_CTA = $FF:0402, 2 ; Color Table Address +VCE_CTW = $FF:0404, 2 ; Color Table Data Write +VCE_CTR = $FF:0404, 2 ; Color Table Data Read XRES_SHARP = $00 XRES_SOFT = $04 @@ -98,28 +98,28 @@ XRES_BW = $80 ; HuC6280 - Programmable Sound Generator ; -PSG_R0 = $FF:0800 ; Channel Select -PSG_R1 = $FF:0801 ; Main Amplitude Level -PSG_R2 = $FF:0802 ; Frequency Low -PSG_R3 = $FF:0803 ; Frequency High -PSG_R4 = $FF:0804 ; Control & Channel Amplitude -PSG_R5 = $FF:0805 ; L/R Amplitude Level -PSG_R6 = $FF:0806 ; Waveform -PSG_R7 = $FF:0807 ; Noise -PSG_R8 = $FF:0808 ; LFO Frequency -PSG_R9 = $FF:0809 ; LFO Control +PSG_R0 = $FF:0800, 1 ; Channel Select +PSG_R1 = $FF:0801, 1 ; Main Amplitude Level +PSG_R2 = $FF:0802, 1 ; Frequency Low +PSG_R3 = $FF:0803, 1 ; Frequency High +PSG_R4 = $FF:0804, 1 ; Control & Channel Amplitude +PSG_R5 = $FF:0805, 1 ; L/R Amplitude Level +PSG_R6 = $FF:0806, 1 ; Waveform +PSG_R7 = $FF:0807, 1 ; Noise +PSG_R8 = $FF:0808, 1 ; LFO Frequency +PSG_R9 = $FF:0809, 1 ; LFO Control -PSG_AR = $FF:0800 ; Channel Select -PSG_VOL = $FF:0801 ; Main Amplitude Level -PSG_FREQ = $FF:0802 ; Frequency Low -PSG_FREQ_LO = $FF:0802 ; Frequency Low -PSG_FREQ_HI = $FF:0803 ; Frequency High -PSG_CTRL = $FF:0804 ; Control & Channel Amplitude -PSG_PAN = $FF:0805 ; L/R Amplitude Level -PSG_WAVEFORM = $FF:0806 ; Waveform -PSG_NOISE = $FF:0807 ; Noise -PSG_LFO_FREQ = $FF:0808 ; LFO Frequency -PSG_LFO_CTRL = $FF:0809 ; LFO Control +PSG_AR = $FF:0800, 1 ; Channel Select +PSG_VOL = $FF:0801, 1 ; Main Amplitude Level +PSG_FREQ = $FF:0802, 1 ; Frequency Low +PSG_FREQ_LO = $FF:0802, 1 ; Frequency Low +PSG_FREQ_HI = $FF:0803, 1 ; Frequency High +PSG_CTRL = $FF:0804, 1 ; Control & Channel Amplitude +PSG_PAN = $FF:0805, 1 ; L/R Amplitude Level +PSG_WAVEFORM = $FF:0806, 1 ; Waveform +PSG_NOISE = $FF:0807, 1 ; Noise +PSG_LFO_FREQ = $FF:0808, 1 ; LFO Frequency +PSG_LFO_CTRL = $FF:0809, 1 ; LFO Control @@ -128,8 +128,8 @@ PSG_LFO_CTRL = $FF:0809 ; LFO Control ; HuC6280 - Timer ; -TIMER_DR = $FF:0C00 ; Timer Data -TIMER_CR = $FF:0C01 ; Timer Control +TIMER_DR = $FF:0C00, 1 ; Timer Data +TIMER_CR = $FF:0C01, 1 ; Timer Control @@ -138,7 +138,7 @@ TIMER_CR = $FF:0C01 ; Timer Control ; HuC6280 - I/O Port ; -IO_PORT = $FF:1000 +IO_PORT = $FF:1000, 1 JOY_L = $0080 JOY_D = $0040 @@ -163,9 +163,9 @@ PORT_SEL = $01 ; HuC6280 - Interrupt Control ; -IRQ_MSK = $FF:1402 ; Interrupt Disable -IRQ_REQ = $FF:1403 ; Interrupt Request -IRQ_ACK = $FF:1403 ; Interrupt Acknowledge +IRQ_MSK = $FF:1402, 1 ; Interrupt Disable +IRQ_REQ = $FF:1403, 1 ; Interrupt Request +IRQ_ACK = $FF:1403, 1 ; Interrupt Acknowledge @@ -174,35 +174,35 @@ IRQ_ACK = $FF:1403 ; Interrupt Acknowledge ; CDROM/ADPCM hardware registers. ; -IFU_SCSI_CTL = $FF:1800 ; _W : SCSI control signals out. -IFU_SCSI_FLG = $FF:1800 ; R_ : SCSI control signals in. -IFU_SCSI_DAT = $FF:1801 ; RW : SCSI data bus. +IFU_SCSI_CTL = $FF:1800, 1 ; _W : SCSI control signals out. +IFU_SCSI_FLG = $FF:1800, 1 ; R_ : SCSI control signals in. +IFU_SCSI_DAT = $FF:1801, 1 ; RW : SCSI data bus. -IFU_SCSI_ACK = $FF:1802 ; RW : Top bit of IFU_IRQ_MSK! -IFU_IRQ_MSK = $FF:1802 ; RW : Interrupt mask, 0=disabled. +IFU_SCSI_ACK = $FF:1802, 1 ; RW : Top bit of IFU_IRQ_MSK! +IFU_IRQ_MSK = $FF:1802, 1 ; RW : Interrupt mask, 0=disabled. -IFU_IRQ_FLG = $FF:1803 ; R_ : Interrupt flags. +IFU_IRQ_FLG = $FF:1803, 1 ; R_ : Interrupt flags. -IFU_HW_RESET = $FF:1804 ; _W : Set bit 1 to reset. +IFU_HW_RESET = $FF:1804, 1 ; _W : Set bit 1 to reset. -IFU_AUDIO_LSB = $FF:1805 ; R_ : Current CD audio. -IFU_AUDIO_MSB = $FF:1806 ; R_ : Current CD audio. -IFU_SUBCODE = $FF:1807 ; R_ : Current subcode. +IFU_AUDIO_LSB = $FF:1805, 1 ; R_ : Current CD audio. +IFU_AUDIO_MSB = $FF:1806, 1 ; R_ : Current CD audio. +IFU_SUBCODE = $FF:1807, 1 ; R_ : Current subcode. -IFU_SCSI_AUTO = $FF:1808 ; R_ : SCSI auto-handshake read. +IFU_SCSI_AUTO = $FF:1808, 1 ; R_ : SCSI auto-handshake read. -IFU_ADPCM_LSB = $FF:1808 ; _W : Temporary address latch. -IFU_ADPCM_MSB = $FF:1809 ; _W : Temporary address latch. -IFU_ADPCM_DAT = $FF:180A ; RW : ADPCM RAM data. -IFU_ADPCM_DMA = $FF:180B ; RW : ADPCM DMA control (bits 0 & 1). -IFU_ADPCM_FLG = $FF:180C ; R- : ADPCM status. -IFU_ADPCM_CTL = $FF:180D ; RW : ADPCM control. -IFU_ADPCM_SPD = $FF:180E ; RW : ADPCM playback clock. +IFU_ADPCM_LSB = $FF:1808, 1 ; _W : Temporary address latch. +IFU_ADPCM_MSB = $FF:1809, 1 ; _W : Temporary address latch. +IFU_ADPCM_DAT = $FF:180A, 1 ; RW : ADPCM RAM data. +IFU_ADPCM_DMA = $FF:180B, 1 ; RW : ADPCM DMA control (bits 0 & 1). +IFU_ADPCM_FLG = $FF:180C, 1 ; R- : ADPCM status. +IFU_ADPCM_CTL = $FF:180D, 1 ; RW : ADPCM control. +IFU_ADPCM_SPD = $FF:180E, 1 ; RW : ADPCM playback clock. -IFU_AUDIO_FADE = $FF:180F ; RW : IFU audio fade control/status. +IFU_AUDIO_FADE = $FF:180F, 1 ; RW : IFU audio fade control/status. -IFU_BRAM_LOCK = $FF:1803 ; _W : -IFU_BRAM_UNLOCK = $FF:1807 ; _W : +IFU_BRAM_LOCK = $FF:1803, 1 ; _W : +IFU_BRAM_UNLOCK = $FF:1807, 1 ; _W : ; IFU interrupt bits in IFU_IRQ_MSK/IFU_IRQ_FLG @@ -245,41 +245,41 @@ ADPCM_RD_BSY = $80 ; Arcade Card ; -ACD0_DATA = $FF:1A00 ; RW : 2 -ACD0_BASE = $FF:1A02 ; RW : 3 -ACD0_INDX = $FF:1A05 ; RW : 2 -ACD0_INCR = $FF:1A07 ; RW : 2 -ACD0_CTRL = $FF:1A09 ; RW : 1 -ACD0_TRIG = $FF:1A0A ; _W : 1 - -ACD1_DATA = $FF:1A10 ; RW : 2 -ACD1_BASE = $FF:1A12 ; RW : 3 -ACD1_INDX = $FF:1A15 ; RW : 2 -ACD1_INCR = $FF:1A17 ; RW : 2 -ACD1_CTRL = $FF:1A19 ; RW : 1 -ACD1_TRIG = $FF:1A1A ; _W : 1 - -ACD2_DATA = $FF:1A20 ; RW : 2 -ACD2_BASE = $FF:1A22 ; RW : 3 -ACD2_INDX = $FF:1A25 ; RW : 2 -ACD2_INCR = $FF:1A27 ; RW : 2 -ACD2_CTRL = $FF:1A29 ; RW : 1 -ACD2_TRIG = $FF:1A2A ; _W : 1 - -ACD3_DATA = $FF:1A30 ; RW : 2 -ACD3_BASE = $FF:1A32 ; RW : 3 -ACD3_INDX = $FF:1A35 ; RW : 2 -ACD3_INCR = $FF:1A37 ; RW : 2 -ACD3_CTRL = $FF:1A39 ; RW : 1 (the bottom 7-bits are readable). -ACD3_TRIG = $FF:1A3A ; _W : 1 - -ACD_SHIFT = $FF:1AE0 ; RW : 4 bytes -ACD_ASL = $FF:1AE4 ; RW : 4-bit signed shift (positive is left). -ACD_ROL = $FF:1AE5 ; RW : 4-bit signed shift (positive is left). - -ACD_VERL = $FF:1AFD ; R_ : -ACD_VERH = $FF:1AFE ; R_ : -ACD_FLAG = $FF:1AFF ; R_ : +ACD0_DATA = $FF:1A00, 2 ; RW +ACD0_BASE = $FF:1A02, 3 ; RW +ACD0_INDX = $FF:1A05, 2 ; RW +ACD0_INCR = $FF:1A07, 2 ; RW +ACD0_CTRL = $FF:1A09, 1 ; RW +ACD0_TRIG = $FF:1A0A, 1 ; _W + +ACD1_DATA = $FF:1A10, 2 ; RW +ACD1_BASE = $FF:1A12, 3 ; RW +ACD1_INDX = $FF:1A15, 2 ; RW +ACD1_INCR = $FF:1A17, 2 ; RW +ACD1_CTRL = $FF:1A19, 1 ; RW +ACD1_TRIG = $FF:1A1A, 1 ; _W + +ACD2_DATA = $FF:1A20, 2 ; RW +ACD2_BASE = $FF:1A22, 3 ; RW +ACD2_INDX = $FF:1A25, 2 ; RW +ACD2_INCR = $FF:1A27, 2 ; RW +ACD2_CTRL = $FF:1A29, 1 ; RW +ACD2_TRIG = $FF:1A2A, 1 ; _W + +ACD3_DATA = $FF:1A30, 2 ; RW +ACD3_BASE = $FF:1A32, 3 ; RW +ACD3_INDX = $FF:1A35, 2 ; RW +ACD3_INCR = $FF:1A37, 2 ; RW +ACD3_CTRL = $FF:1A39, 1 ; RW (the bottom 7-bits are readable). +ACD3_TRIG = $FF:1A3A, 1 ; _W + +ACD_SHIFT = $FF:1AE0, 4 ; RW : 4 bytes +ACD_ASL = $FF:1AE4, 1 ; RW : 4-bit signed shift (positive is left). +ACD_ROL = $FF:1AE5, 1 ; RW : 4-bit signed shift (positive is left). + +ACD_VERL = $FF:1AFD, 1 ; R_ : +ACD_VERH = $FF:1AFE, 1 ; R_ : +ACD_FLAG = $FF:1AFF, 1 ; R_ : ACD_ID = $51 ; If ACD_FLAG == ACD_ID, then ACD exists. @@ -291,50 +291,50 @@ ACD_ID = $51 ; If ACD_FLAG == ACD_ID, then ACD exists. ; zpg_grp_top = $F8:20DC -vi_bitpat = $F8:20DC -vi_rvbitpat = $F8:20DD -vi_ft_front = $F8:20DE -vi_padrs = $F8:20DE -vi_porg = $F8:20E0 -vi_ft_back = $F8:20E1 -vi_stack = $F8:20E4 +vi_bitpat = $F8:20DC, 1 +vi_rvbitpat = $F8:20DD, 1 +vi_ft_front = $F8:20DE, 2 +vi_padrs = $F8:20DE, 2 +vi_porg = $F8:20E0, 1 +vi_ft_back = $F8:20E1, 3 +vi_stack = $F8:20E4, 2 zpg_psg_top = $F8:20E6 -time_sw = $F8:20E6 ; psg irq mutex (NZ == already running) -main_sw = $F8:20E7 ; psg driver mode ($80 == disable) -psg_si = $F8:20E8 ; -psg_si_l = $F8:20E8 ; -psg_si_h = $F8:20E9 ; -psg_r0 = $F8:20EA ; -psg_r0_l = $F8:20EA ; -psg_r0_h = $F8:20EB ; +time_sw = $F8:20E6, 1 ; psg irq mutex (NZ == already running) +main_sw = $F8:20E7, 1 ; psg driver mode ($80 == disable) +psg_si = $F8:20E8, 2 ; +psg_si_l = $F8:20E8, 1 ; +psg_si_h = $F8:20E9, 1 ; +psg_r0 = $F8:20EA, 2 ; +psg_r0_l = $F8:20EA, 1 ; +psg_r0_h = $F8:20EB, 1 ; zpg_sys_top = $F8:20EC -_bp = $F8:20EC ; base pointer -_si = $F8:20EE ; source address -_di = $F8:20F0 ; destination address -cdi_b = $F8:20F2 ; IRQ2 interrupt status (like vdc_sr) -vdc_crl = $F8:20F3 ; shadow of VDC control register (lo-byte) -vdc_crh = $F8:20F4 ; shadow of VDC control register (hi-byte) -irq_vec = $F8:20F5 ; interrupt vector control mask -vdc_sr = $F8:20F6 ; shadow of VDC status register -vdc_reg = $F8:20F7 ; shadow of VDC register index +_bp = $F8:20EC, 2 ; base pointer +_si = $F8:20EE, 2 ; source address +_di = $F8:20F0, 2 ; destination address +cdi_b = $F8:20F2, 1 ; IRQ2 interrupt status (like vdc_sr) +vdc_crl = $F8:20F3, 1 ; shadow of VDC control register (lo-byte) +vdc_crh = $F8:20F4, 1 ; shadow of VDC control register (hi-byte) +irq_vec = $F8:20F5, 1 ; interrupt vector control mask +vdc_sr = $F8:20F6, 1 ; shadow of VDC status register +vdc_reg = $F8:20F7, 1 ; shadow of VDC register index -_ax = $F8:20F8 -_al = $F8:20F8 -_ah = $F8:20F9 +_ax = $F8:20F8, 2 +_al = $F8:20F8, 1 +_ah = $F8:20F9, 1 -_bx = $F8:20FA -_bl = $F8:20FA -_bh = $F8:20FB +_bx = $F8:20FA, 2 +_bl = $F8:20FA, 1 +_bh = $F8:20FB, 1 -_cx = $F8:20FC -_cl = $F8:20FC -_ch = $F8:20FD +_cx = $F8:20FC, 2 +_cl = $F8:20FC, 1 +_ch = $F8:20FD, 1 -_dx = $F8:20FE -_dl = $F8:20FE -_dh = $F8:20FF +_dx = $F8:20FE, 2 +_dl = $F8:20FE, 1 +_dh = $F8:20FF, 1 @@ -343,110 +343,109 @@ _dh = $F8:20FF ; System Card's Main RAM Variables. ; -irq2_hook = $F8:2200 ; 2 officially called irq2_jmp -irq1_hook = $F8:2202 ; 2 officially called irq_jmp -timer_hook = $F8:2204 ; 2 officially called tim_jmp -nmi_hook = $F8:2206 ; 2 officially called nmi_jmp -vsync_hook = $F8:2208 ; 2 officially called sync_jmp -hsync_hook = $F8:220A ; 2 officially called rcr_jmp -bg_x1 = $F8:220C ; 2 officially called bgx1 -bg_x2 = $F8:220E ; 2 -bg_y1 = $F8:2210 ; 2 -bg_y2 = $F8:2212 ; 2 -satb_addr = $F8:2214 ; 2 officially called sat_adr -sprptr = $F8:2216 ; 1 -spryl = $F8:2217 ; 1 -spryh = $F8:2218 ; 1 -sprxl = $F8:2219 ; 1 -sprxh = $F8:221A ; 1 -sprnl = $F8:221B ; 1 -sprnh = $F8:221C ; 1 -spral = $F8:221D ; 1 -sprah = $F8:221E ; 1 -color_cmd = $F8:221F ; 1 -bgc_ptr = $F8:2220 ; 2 -bgc_len = $F8:2222 ; 1 -sprc_ptr = $F8:2223 ; 2 -sprc_len = $F8:2225 ; 1 -joyena = $F8:2227 ; 1 -joynow = $F8:2228 ; 5 officially called joy -joytrg = $F8:222D ; 5 -joyold = $F8:2232 ; 5 -irq_cnt = $F8:2241 ; 1 -vdc_mwr = $F8:2242 ; 1 officially called mwr_m -vdc_dcr = $F8:2243 ; 1 officially called dcr_m -vce_cr = $F8:2244 ; 1 *UNDOCUMENTED* set by ex_scrmod (not 10MHz!) -vdc_hdw = $F8:2245 ; 1 *UNDOCUMENTED* set by ex_scrmod -vdc_vdw = $F8:2246 ; 1 *UNDOCUMENTED* set by ex_scrmod -cd_not_rdy = $F8:2247 ; 1 *UNDOCUMENTED* set if CDERR_NOT_READY from scsi_req_sense() -cd_searching = $F8:2248 ; 1 *UNDOCUMENTED* 1 when background cd_search() requested -rndseed = $F8:2249 ; 1 -rndl = $F8:2249 ; 1 -rndh = $F8:224A ; 1 -rndm = $F8:224B ; 1 -scsi_send_buf = $F8:224C ; 10 *UNDOCUMENTED* buffer for SCSI cmd send -scsi_recv_buf = $F8:2256 ; 10 *UNDOCUMENTED* buffer for SCSI cmd recv -parameter_buf = $F8:2260 ; 8 *UNDOCUMENTED* stored _ax,_bx,_cx,_dx -initialmpr = $F8:2268 ; 1 *UNDOCUMENTED* -;? = $F8:2269 ; ? *UNDOCUMENTED* subcode -tnomin = $F8:226A ; 1 -tnomax = $F8:226B ; 1 -outmin = $F8:226C ; 1 -outsec = $F8:226D ; 1 -outfrm = $F8:226E ; 1 -endmin = $F8:226F ; 1 *UNDOCUMENTED* -endsec = $F8:2270 ; 1 *UNDOCUMENTED* -endfrm = $F8:2271 ; 1 *UNDOCUMENTED* -vdtin_flg = $F8:2272 ; 1 -recbase = $F8:2273 ; 1 *UNDOCUMENTED* active recbase (0 or 1) -recbase0_h = $F8:2274 ; 1 -recbase0_m = $F8:2275 ; 1 -recbase0_l = $F8:2276 ; 1 -recbase1_h = $F8:2277 ; 1 -recbase1_m = $F8:2278 ; 1 -recbase1_l = $F8:2279 ; 1 -scsiphs = $F8:227A ; 1 *UNDOCUMENTED* SCSI command phase -scsists = $F8:227B ; 1 -suberrc = $F8:227C ; 1 -scsisns = $F8:227D ; 1 *UNDOCUMENTED* unused SCSI "sense" return code -subcode = $F8:227E ; 1 WRITE-ONLY! -;? = $F8:227F ; 1 *UNDOCUMENTED* unused, never accessed! - -reset_hook = $F8:2284 ; 2 *UNDOCUMENTED* joypad soft-reset hook -color_tia = $F8:2286 ; 8 *UNDOCUMENTED* self-mod TIA used by ex_colorcmd -;? = $F8:228E ; 3 *UNDOCUMENTED* self-mod TMA/TAM used by cd_read/ad_read/ad_write -;? = $F8:2291 ; 10 *UNDOCUMENTED* copy of scsisend made by cd_read (never read) -reset_cdrom = $F8:229B ; 1 *UNDOCUMENTED* NZ if CD reset is needed -cdplay_mode = $F8:229C ; 1 *UNDOCUMENTED* - -cplay_siz_l = $F8:229D ; 1 *UNDOCUMENTED* ad_cplay streaming sector load size (low) -cplay_len_l = $F8:229E ; 1 *UNDOCUMENTED* ad_cplay streaming length (low/mid/high) -cplay_len_m = $F8:229F ; 1 *UNDOCUMENTED* ad_cplay streaming length (low/mid/high) -cplay_len_h = $F8:22A0 ; 1 *UNDOCUMENTED* ad_cplay streaming length (low/mid/high) -cplay_lba_h = $F8:22A1 ; 1 *UNDOCUMENTED* ad_cplay streaming sector (high/mid/low) -cplay_lba_m = $F8:22A2 ; 1 *UNDOCUMENTED* ad_cplay streaming sector (high/mid/low) -cplay_lba_l = $F8:22A3 ; 1 *UNDOCUMENTED* ad_cplay streaming sector (high/mid/low) -bios_cd_mutex = $F8:22A4 ; 1 *UNDOCUMENTED* NZ if BIOS is using the CD in the background -ad_play_mode = $F8:22A5 ; 1 *UNDOCUMENTED* -ad_play_size = $F8:22A6 ; 2 *UNDOCUMENTED* -ad_play_addr = $F8:22A8 ; 2 *UNDOCUMENTED* -ad_play_rate = $F8:22AA ; 1 *UNDOCUMENTED* - -;bram_count = $F8:22B3 ; 2 *UNDOCUMENTED* -;mprsav = $F8:22B5 ; 8 *UNDOCUMENTED* backups of MPR when BIOS needs major bank swapping. -;? = $F8:22BD ; 1 *UNDOCUMENTED* -;? = $F8:22BE ; 1 *UNDOCUMENTED* - -;? = $F8:22C1 ; 1 *UNDOCUMENTED* -;? = $F8:22C2 ; 1 *UNDOCUMENTED* -;? = $F8:22C3 ; 1 *UNDOCUMENTED* -;? = $F8:22C4 ; 1 *UNDOCUMENTED* - -ramend = $F8:22D0 ; 1 +irq2_hook = $F8:2200, 2 ; officially called irq2_jmp +irq1_hook = $F8:2202, 2 ; officially called irq_jmp +timer_hook = $F8:2204, 2 ; officially called tim_jmp +nmi_hook = $F8:2206, 2 ; officially called nmi_jmp +vsync_hook = $F8:2208, 2 ; officially called sync_jmp +hsync_hook = $F8:220A, 2 ; officially called rcr_jmp +bg_x1 = $F8:220C, 2 ; officially called bgx1 +bg_x2 = $F8:220E, 2 +bg_y1 = $F8:2210, 2 +bg_y2 = $F8:2212, 2 +satb_addr = $F8:2214, 2 ; officially called sat_adr +sprptr = $F8:2216, 1 +spryl = $F8:2217, 1 +spryh = $F8:2218, 1 +sprxl = $F8:2219, 1 +sprxh = $F8:221A, 1 +sprnl = $F8:221B, 1 +sprnh = $F8:221C, 1 +spral = $F8:221D, 1 +sprah = $F8:221E, 1 +color_cmd = $F8:221F, 1 +bgc_ptr = $F8:2220, 2 +bgc_len = $F8:2222, 1 +sprc_ptr = $F8:2223, 2 +sprc_len = $F8:2225, 1 +joyena = $F8:2227, 1 +joynow = $F8:2228, 5 ; officially called joy +joytrg = $F8:222D, 5 +joyold = $F8:2232, 5 +irq_cnt = $F8:2241, 1 +vdc_mwr = $F8:2242, 1 ; officially called mwr_m +vdc_dcr = $F8:2243, 1 ; officially called dcr_m +vce_cr = $F8:2244, 1 ; *UNDOCUMENTED* set by ex_scrmod (not 10MHz!) +vdc_hdw = $F8:2245, 1 ; *UNDOCUMENTED* set by ex_scrmod +vdc_vdw = $F8:2246, 1 ; *UNDOCUMENTED* set by ex_scrmod +cd_not_rdy = $F8:2247, 1 ; *UNDOCUMENTED* set if CDERR_NOT_READY from scsi_req_sense() +cd_searching = $F8:2248, 1 ; *UNDOCUMENTED* 1 when background cd_search() requested +rndseed = $F8:2249, 1 +rndl = $F8:2249, 1 +rndh = $F8:224A, 1 +rndm = $F8:224B, 1 +scsi_send_buf = $F8:224C, 10 ; *UNDOCUMENTED* buffer for SCSI cmd send +scsi_recv_buf = $F8:2256, 10 ; *UNDOCUMENTED* buffer for SCSI cmd recv +parameter_buf = $F8:2260, 8 ; *UNDOCUMENTED* stored _ax,_bx,_cx,_dx +initialmpr = $F8:2268, 1 ; *UNDOCUMENTED* +;? = $F8:2269, ? ; *UNDOCUMENTED* subcode +tnomin = $F8:226A, 1 +tnomax = $F8:226B, 1 +outmin = $F8:226C, 1 +outsec = $F8:226D, 1 +outfrm = $F8:226E, 1 +endmin = $F8:226F, 1 ; *UNDOCUMENTED* +endsec = $F8:2270, 1 ; *UNDOCUMENTED* +endfrm = $F8:2271, 1 ; *UNDOCUMENTED* +vdtin_flg = $F8:2272, 1 +recbase = $F8:2273, 1 ; *UNDOCUMENTED* active recbase (0 or 1) +recbase0_h = $F8:2274, 1 +recbase0_m = $F8:2275, 1 +recbase0_l = $F8:2276, 1 +recbase1_h = $F8:2277, 1 +recbase1_m = $F8:2278, 1 +recbase1_l = $F8:2279, 1 +scsiphs = $F8:227A, 1 ; *UNDOCUMENTED* SCSI command phase +scsists = $F8:227B, 1 +suberrc = $F8:227C, 1 +scsisns = $F8:227D, 1 ; *UNDOCUMENTED* unused SCSI "sense" return code +subcode = $F8:227E, 1 ; WRITE-ONLY! +;? = $F8:227F, 1 ; *UNDOCUMENTED* unused, never accessed! + +reset_hook = $F8:2284, 2 ; *UNDOCUMENTED* joypad soft-reset hook +color_tia = $F8:2286, 8 ; *UNDOCUMENTED* self-mod TIA used by ex_colorcmd +;? = $F8:228E, 3 ; *UNDOCUMENTED* self-mod TMA/TAM used by cd_read/ad_read/ad_write +;? = $F8:2291, 10 ; *UNDOCUMENTED* copy of scsisend made by cd_read (never read) +reset_cdrom = $F8:229B, 1 ; *UNDOCUMENTED* NZ if CD reset is needed +cdplay_mode = $F8:229C, 1 ; *UNDOCUMENTED* + +cplay_siz_l = $F8:229D, 1 ; *UNDOCUMENTED* ad_cplay streaming sector load size (low) +cplay_len_l = $F8:229E, 1 ; *UNDOCUMENTED* ad_cplay streaming length (low/mid/high) +cplay_len_m = $F8:229F, 1 ; *UNDOCUMENTED* ad_cplay streaming length (low/mid/high) +cplay_len_h = $F8:22A0, 1 ; *UNDOCUMENTED* ad_cplay streaming length (low/mid/high) +cplay_lba_h = $F8:22A1, 1 ; *UNDOCUMENTED* ad_cplay streaming sector (high/mid/low) +cplay_lba_m = $F8:22A2, 1 ; *UNDOCUMENTED* ad_cplay streaming sector (high/mid/low) +cplay_lba_l = $F8:22A3, 1 ; *UNDOCUMENTED* ad_cplay streaming sector (high/mid/low) +bios_cd_mutex = $F8:22A4, 1 ; *UNDOCUMENTED* NZ if BIOS is using the CD in the background +ad_play_mode = $F8:22A5, 1 ; *UNDOCUMENTED* +ad_play_size = $F8:22A6, 2 ; *UNDOCUMENTED* +ad_play_addr = $F8:22A8, 2 ; *UNDOCUMENTED* +ad_play_rate = $F8:22AA, 1 ; *UNDOCUMENTED* + +;bram_count = $F8:22B3, 2 ; *UNDOCUMENTED* +;mprsav = $F8:22B5, 8 ; *UNDOCUMENTED* backups of MPR when BIOS needs major bank swapping. +;? = $F8:22BD, 1 ; *UNDOCUMENTED* +;? = $F8:22BE, 1 ; *UNDOCUMENTED* + +;? = $F8:22C1, 1 ; *UNDOCUMENTED* +;? = $F8:22C2, 1 ; *UNDOCUMENTED* +;? = $F8:22C3, 1 ; *UNDOCUMENTED* +;? = $F8:22C4, 1 ; *UNDOCUMENTED* + +ramend = $F8:22D0, 1 psg_work_top = $F8:22D0 -psg_reg = $F8:22ED ; 1 shadow for selected PSG register, like vdc_reg - ; ... +psg_reg = $F8:22ED, 1 ; shadow for selected PSG register, like vdc_reg graph_work_top = $F8:2616 key_work_top = $F8:2646 @@ -459,93 +458,95 @@ user_work_top = $F8:267C ; System Card's Function Vectors ; -cd_boot = $00:E000 -cd_reset = $00:E003 -cd_base = $00:E006 -cd_read = $00:E009 -cd_seek = $00:E00C -cd_exec = $00:E00F -cd_play = $00:E012 -cd_search = $00:E015 -cd_pause = $00:E018 -cd_stat = $00:E01B -cd_subq = $00:E01E -cd_dinfo = $00:E021 -cd_contnts = $00:E024 -cd_subrd = $00:E027 -cd_pcmrd = $00:E02A -cd_fade = $00:E02D - -ad_reset = $00:E030 -ad_trans = $00:E033 -ad_read = $00:E036 -ad_write = $00:E039 -ad_play = $00:E03C -ad_cplay = $00:E03F -ad_stop = $00:E042 -ad_stat = $00:E045 - -bm_format = $00:E048 -bm_free = $00:E04B -bm_read = $00:E04E -bm_write = $00:E051 -bm_delete = $00:E054 -bm_files = $00:E057 - -ex_getver = $00:E05A -ex_setvec = $00:E05D -ex_getfnt = $00:E060 -ex_joysns = $00:E063 -ex_joyrep = $00:E066 -ex_scrsiz = $00:E069 -ex_dotmod = $00:E06C -ex_scrmod = $00:E06F -ex_imode = $00:E072 -ex_vmode = $00:E075 -ex_hmode = $00:E078 -ex_vsync = $00:E07B -ex_rcron = $00:E07E -ex_rcroff = $00:E081 -ex_irqon = $00:E084 -ex_irqoff = $00:E087 -ex_bgon = $00:E08A -ex_bgoff = $00:E08D -ex_spron = $00:E090 -ex_sproff = $00:E093 -ex_dspon = $00:E096 -ex_dspoff = $00:E099 -ex_dmamod = $00:E09C -ex_sprdma = $00:E09F -ex_satclr = $00:E0A2 -ex_sprput = $00:E0A5 -ex_setrcr = $00:E0A8 -ex_setred = $00:E0AB -ex_setwrt = $00:E0AE -ex_setdma = $00:E0B1 -ex_binbcd = $00:E0B4 -ex_bcdbin = $00:E0B7 -ex_rnd = $00:E0BA - -ma_mul8u = $00:E0BD -ma_mul8s = $00:E0C0 -ma_mul16u = $00:E0C3 -ma_div16s = $00:E0C6 -ma_div16u = $00:E0C9 -ma_sqrt = $00:E0CC -ma_sin = $00:E0CF -ma_cos = $00:E0D2 -ma_atni = $00:E0D5 - -psg_bios = $00:E0D8 -grp_bios = $00:E0DB - -ex_memopen = $00:E0DE - -psg_driver = $00:E0E1 - -ex_colorcmd = $00:E0E4 - -max_mapping = $00:FFF5 + .if CDROM +cd_boot = $00:E000, FUNC +cd_reset = $00:E003, FUNC +cd_base = $00:E006, FUNC +cd_read = $00:E009, FUNC +cd_seek = $00:E00C, FUNC +cd_exec = $00:E00F, FUNC +cd_play = $00:E012, FUNC +cd_search = $00:E015, FUNC +cd_pause = $00:E018, FUNC +cd_stat = $00:E01B, FUNC +cd_subq = $00:E01E, FUNC +cd_dinfo = $00:E021, FUNC +cd_contnts = $00:E024, FUNC +cd_subrd = $00:E027, FUNC +cd_pcmrd = $00:E02A, FUNC +cd_fade = $00:E02D, FUNC + +ad_reset = $00:E030, FUNC +ad_trans = $00:E033, FUNC +ad_read = $00:E036, FUNC +ad_write = $00:E039, FUNC +ad_play = $00:E03C, FUNC +ad_cplay = $00:E03F, FUNC +ad_stop = $00:E042, FUNC +ad_stat = $00:E045, FUNC + +bm_format = $00:E048, FUNC +bm_free = $00:E04B, FUNC +bm_read = $00:E04E, FUNC +bm_write = $00:E051, FUNC +bm_delete = $00:E054, FUNC +bm_files = $00:E057, FUNC + +ex_getver = $00:E05A, FUNC +ex_setvec = $00:E05D, FUNC +ex_getfnt = $00:E060, FUNC +ex_joysns = $00:E063, FUNC +ex_joyrep = $00:E066, FUNC +ex_scrsiz = $00:E069, FUNC +ex_dotmod = $00:E06C, FUNC +ex_scrmod = $00:E06F, FUNC +ex_imode = $00:E072, FUNC +ex_vmode = $00:E075, FUNC +ex_hmode = $00:E078, FUNC +ex_vsync = $00:E07B, FUNC +ex_rcron = $00:E07E, FUNC +ex_rcroff = $00:E081, FUNC +ex_irqon = $00:E084, FUNC +ex_irqoff = $00:E087, FUNC +ex_bgon = $00:E08A, FUNC +ex_bgoff = $00:E08D, FUNC +ex_spron = $00:E090, FUNC +ex_sproff = $00:E093, FUNC +ex_dspon = $00:E096, FUNC +ex_dspoff = $00:E099, FUNC +ex_dmamod = $00:E09C, FUNC +ex_sprdma = $00:E09F, FUNC +ex_satclr = $00:E0A2, FUNC +ex_sprput = $00:E0A5, FUNC +ex_setrcr = $00:E0A8, FUNC +ex_setred = $00:E0AB, FUNC +ex_setwrt = $00:E0AE, FUNC +ex_setdma = $00:E0B1, FUNC +ex_binbcd = $00:E0B4, FUNC +ex_bcdbin = $00:E0B7, FUNC +ex_rnd = $00:E0BA, FUNC + +ma_mul8u = $00:E0BD, FUNC +ma_mul8s = $00:E0C0, FUNC +ma_mul16u = $00:E0C3, FUNC +ma_div16s = $00:E0C6, FUNC +ma_div16u = $00:E0C9, FUNC +ma_sqrt = $00:E0CC, FUNC +ma_sin = $00:E0CF, FUNC +ma_cos = $00:E0D2, FUNC +ma_atni = $00:E0D5, FUNC + +psg_bios = $00:E0D8, FUNC +grp_bios = $00:E0DB, FUNC + +ex_memopen = $00:E0DE, FUNC + +psg_driver = $00:E0E1, FUNC + +ex_colorcmd = $00:E0E4, FUNC + +max_mapping = $00:FFF5, 1 + .endif CDROM @@ -554,6 +555,7 @@ max_mapping = $00:FFF5 ; System Card's PSG BIOS call functions. ; + .if CDROM PSG_ON = 0 PSG_OFF = 1 PSG_INIT = 2 @@ -575,6 +577,7 @@ PSG_MVOFF = 17 PSG_CONT = 18 PSG_FDOUT = 19 PSG_DCNT = 20 + .endif CDROM @@ -583,6 +586,7 @@ PSG_DCNT = 20 ; System Card's GRP BIOS call functions. ; + .if CDROM VI_GINIT = 0 VI_CASHCLR = 1 VI_STRTADR = 2 @@ -599,6 +603,7 @@ VI_GWINDOW = 12 VI_GFONT = 13 VI_PUTFONT = 14 VI_SYMBOL = 15 + .endif CDROM diff --git a/src/hucc/code.c b/src/hucc/code.c index bb3cc8be..7d1f72ec 100644 --- a/src/hucc/code.c +++ b/src/hucc/code.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,21 @@ void out_ins_ex (int code, int type, intptr_t data, int imm_type, intptr_t imm_d gen_ins(&tmp); } +void out_ins_ex_arg (int code, int type, intptr_t data, int imm_type, intptr_t imm_data, char * string) +{ + INS tmp; + + memset(&tmp, 0, sizeof(INS)); + + tmp.ins_code = code; + tmp.ins_type = type; + tmp.ins_data = data; + tmp.imm_type = imm_type; + tmp.imm_data = imm_data; + tmp.arg[0] = string; + gen_ins(&tmp); +} + void out_ins_sym (int code, int type, intptr_t data, SYMBOL *sym) { INS tmp; @@ -288,6 +304,37 @@ void gen_code (INS *tmp) switch (code) { + /* i-code for debug information */ + + case I_DEBUG: + switch(type) { + case T_SOURCE_LINE: + if (data) { + char * source = (char *)data; + if (source) + while (source[0] == ' ' || source[0] == '\t') + ++source; + nl(); + ot(".dbg\tline,\t\""); + if (tmp->arg[0]) { + outstr(tmp->arg[0]); + } + outstr("\", "); + outdec((int)imm_data); + outstr("; "); + outstr(source); + nl(); + free((void *)data); + } + break; + case T_CLEAR_LINE: + nl(); + ol(".dbg\tclear"); + break; + + } + break; + /* i-code that retires the primary register contents */ case I_FENCE: @@ -400,7 +447,7 @@ void gen_code (INS *tmp) in HuC we get a string and not a symbol */ switch (type) { case T_LITERAL: - ot(" call\t\t"); + ot("__call\t\t"); prefix(); outstr((const char *)data); if (imm_data) { @@ -429,7 +476,7 @@ void gen_code (INS *tmp) break; case I_RETURN: - ot("__return\t\t"); + ot("__return\t"); outdec((int)data); nl(); break; @@ -497,6 +544,10 @@ void gen_code (INS *tmp) nl(); break; + case I_DEFAULT: + ol("__default"); + break; + case I_CASE: ot("__case\t\t"); if (type == T_VALUE) @@ -505,8 +556,7 @@ void gen_code (INS *tmp) break; case I_ENDCASE: - ot("__endcase"); - nl(); + ol("__endcase"); break; case I_LABEL: @@ -531,14 +581,12 @@ void gen_code (INS *tmp) ot("__bfalse\t"); outlabel((int)data); nl(); - nl(); break; case I_BTRUE: ot("__btrue\t\t"); outlabel((int)data); nl(); - nl(); break; case I_DEF: diff --git a/src/hucc/code.h b/src/hucc/code.h index 5f62b6ba..5f9ba1f5 100644 --- a/src/hucc/code.h +++ b/src/hucc/code.h @@ -20,6 +20,7 @@ void defstorage (void); void defword (void); void out_ins (int code, int type, intptr_t data); void out_ins_ex (int code, int type, intptr_t data, int imm_type, intptr_t imm_data); +void out_ins_ex_arg (int code, int type, intptr_t data, int imm_type, intptr_t imm_data, char * string); void out_ins_sym (int code, int type, intptr_t data, SYMBOL *sym); void out_ins_cmp (int code, int type); void gen_ins (INS *tmp); diff --git a/src/hucc/const.c b/src/hucc/const.c index c0f739bc..324ce932 100644 --- a/src/hucc/const.c +++ b/src/hucc/const.c @@ -161,7 +161,7 @@ int get_string_ptr (char typ) if (typ == CINT || typ == CUINT) error("incompatible pointer type"); - if (qstr(&num)) + if (quoted_str(&num)) return (-(num + 1024)); else return (-1); @@ -255,6 +255,16 @@ int get_raw_value (char sep) } /* add char */ + if (c == '^') { + /* we want the succeeding identifier's bank */ + is_address = 1; + /* we need to remember that we had an address + somewhere so we can barf if the identifier + contains arithmetic */ + had_address = 1; + /* drop through and add the '^' to the const_data[] */ + } + if (c == '&') { /* we want the succeeding identifier's address */ is_address = 1; diff --git a/src/hucc/data.c b/src/hucc/data.c index 52948503..be85881a 100644 --- a/src/hucc/data.c +++ b/src/hucc/data.c @@ -95,6 +95,7 @@ int ted2flag; int verboseflag; int startup_incl; int errs; +char debug_info; int norecurse = 0; #if ULI_NORECURSE diff --git a/src/hucc/data.h b/src/hucc/data.h index 3d6243e4..fd829581 100644 --- a/src/hucc/data.h +++ b/src/hucc/data.h @@ -89,6 +89,7 @@ extern int ted2flag; extern int verboseflag; extern int startup_incl; extern int errs; +extern char debug_info; extern int top_level_stkp; extern int norecurse; diff --git a/src/hucc/defs.h b/src/hucc/defs.h index 78e099f3..195075c9 100644 --- a/src/hucc/defs.h +++ b/src/hucc/defs.h @@ -12,9 +12,13 @@ * as the table of i-code flag information in optimize.c */ enum ICODE { + /* i-code for debug information */ + + I_DEBUG = 1, + /* i-code that retires the primary register contents */ - I_FENCE = 1, + I_FENCE, /* i-code that declares a byte sized primary register */ @@ -60,6 +64,7 @@ enum ICODE { I_SWITCH_WR, I_SWITCH_UR, + I_DEFAULT, I_CASE, I_ENDCASE, I_LABEL, @@ -385,6 +390,8 @@ enum ICOMPARE { #define T_VRAM 9 #define T_PAL 10 #define T_LITERAL 11 +#define T_SOURCE_LINE 12 +#define T_CLEAR_LINE 13 #define FOREVER for (;;) #define FALSE 0 @@ -401,7 +408,11 @@ enum ICOMPARE { #define FFEED 12 #define TAB 9 -#define FILENAMESIZE 256 +#ifdef _WIN32 +#define FILENAMESIZE 260 +#else +#define FILENAMESIZE 256 +#endif /* symbol table parameters (locals are reset for every function) */ #define SYMTBSZ 4096 @@ -503,7 +514,7 @@ struct tag_symbol { #define WS_INCR_LABEL 4 #define WS_DEFAULT_LABEL 4 #define WS_BODY_LABEL 5 -#define WS_TABLE_LABEL 5 /* label for dumpswitch() data table */ +#define WS_SWITCH_LABEL 5 #define WS_EXIT_LABEL 6 /* possible entries for "WS_TYPE" */ @@ -528,7 +539,7 @@ struct tag_symbol { /* input line */ -#define LINESIZE 384 +#define LINESIZE 512 #define LINEMAX (LINESIZE - 1) #define MPMAX LINEMAX diff --git a/src/hucc/function.c b/src/hucc/function.c index 8434cc90..bf758a58 100644 --- a/src/hucc/function.c +++ b/src/hucc/function.c @@ -379,8 +379,9 @@ void newfunc (const char *sname, int ret_ptr_order, int ret_type, int ret_otag, flush_ins(); /* David, .proc directive support */ gtext(); - comment(); - outstr("*******\n\n"); + outstr(";***********************\n"); + outstr(";***********************\n"); + nl(); ol(".hucc"); ot(".proc\t\t"); prefix(); @@ -415,6 +416,7 @@ void newfunc (const char *sname, int ret_ptr_order, int ret_type, int ret_otag, out_ins(I_RETURN, T_VALUE, ret_type != CVOID || ret_ptr_order != 0); /* generate the return statement */ flush_ins(); /* David, optimize.c related */ + ol(".dbg\tclear"); ol(".endp"); /* David, .endp directive support */ #if ULI_NORECURSE diff --git a/src/hucc/gen.c b/src/hucc/gen.c index 97d1ad50..3ae0a935 100644 --- a/src/hucc/gen.c +++ b/src/hucc/gen.c @@ -281,16 +281,23 @@ void gswitch (int nlab) } /* - * mark the start of a case or default statement + * mark the start of a case statement */ void gcase (int nlab, int value) { out_ins(I_ENDCASE, 0, 0); gnlabel(nlab); - if (value == INT_MAX) - out_ins(I_CASE, 0, 0); - else - out_ins(I_CASE, T_VALUE, value); + out_ins(I_CASE, T_VALUE, value); +} + +/* + * mark the start of a default statement + */ +void gdefault (int nlab) +{ + out_ins(I_ENDCASE, 0, 0); + gnlabel(nlab); + out_ins(I_DEFAULT, 0, 0); } /* diff --git a/src/hucc/gen.h b/src/hucc/gen.h index 2a1ecaff..7b1a1ac9 100644 --- a/src/hucc/gen.h +++ b/src/hucc/gen.h @@ -21,6 +21,7 @@ void gaslint (void); void gasrint (void); void gswitch (int nlab); void gcase (int nlab, int value); +void gdefault (int nlab); void gadd (LVALUE *lval, LVALUE *lval2); void gsub (void); void gmult (int is_unsigned); diff --git a/src/hucc/io.c b/src/hucc/io.c index d9707c0b..b2fa79a1 100644 --- a/src/hucc/io.c +++ b/src/hucc/io.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "defs.h" #include "data.h" @@ -17,41 +18,41 @@ #include "sym.h" /* - * open input file + * open input file + * * Input : char* p * Output : int error code * * Try to open the file whose filename is p, return YES if opened, else NO * Updates fname with the actual opened name * input is the handle of the opened file - * */ int openin (char *p) { - strcpy(fname, p); - strcpy(fname_copy, fname); - fixname(fname); - if (!checkname(fname)) { - fprintf(stderr, "%s: unknown file type\n", fname); +// fixname(fname); + if (!checkname(p)) { + fprintf(stderr, "%s: unknown file type\n", p); return (NO); } - if ((input = fopen(fname, "r")) == NULL) { - perror(fname); + if ((input = file_open(p, 0)) == NULL) { + perror(p); return (NO); } + strcpy(fname, inclstk_name[inclsp]); + strcpy(fname_copy, fname); kill(); return (YES); } /* - * open output file + * open output file + * * Input : nothing but uses global fname * Output : nothing but fname contain the name of the out file now * * Guess the name of the outfile thanks to the input one and try to open it * In case of succes returns YES and output is the handle of the opened file * else returns NO - * */ int openout (void) { @@ -75,13 +76,13 @@ int openout (void) } /* - * change input filename to output filename + * change input filename to output filename + * * Input : char* s * Output : char* s is updated * * Simply replace the last letter of s by 's' * Used to return "file.s" from "file.c" - * */ void outfname (char *s) { @@ -91,12 +92,12 @@ void outfname (char *s) } /* - * remove NL from filenames + * remove NL from filenames + * * Input : char* s * Output : char* s is updated * * if any, remove the trailing newline char from the s string - * */ void fixname (char *s) { @@ -107,13 +108,13 @@ void fixname (char *s) } /* - * check that filename is "*.c" + * check that filename is "*.c" + * * Input : char* s * Output : int * * verify that the 2 last letter of s are ".c", returns YES in this case, * else NO - * */ int checkname (char *s) { @@ -129,13 +130,13 @@ int checkname (char *s) } /* - * kill + * kill + * * Input : nothing * Output : nothing but updates lptr and line[lptr] * * lptr and line[lptr] are set to zero what appears to clear the current * input line - * */ void kill (void) { @@ -145,6 +146,7 @@ void kill (void) /* * unget_line + * * Input : # of characters to kill preceding what we see in line[lptr] * Output : nothing * @@ -154,7 +156,6 @@ void kill (void) * * Only use this function for operations at the top level (ie. the * file pointer 'fp') - * */ void unget_line (void) { @@ -171,13 +172,13 @@ void unget_line (void) /* - * readline + * readline + * * Input : nothing * Output : nothing * * This function seems to fill line and lptr variables with a line of text - * coming either form an included file or the main one - * + * coming either from an included file or the main one */ void readline (void) { @@ -202,6 +203,7 @@ void readline (void) if (input2 != NULL) { if (globals_h_in_process) { /* Add special treatment to ensure globals.h stuff appears at the beginning */ + ol(".dbg\tclear"); gdata(); outstr("huc_globals:\n"); dumpglbs(); @@ -214,17 +216,31 @@ void readline (void) fclose(unit); } if (lptr) { + char * filename = (inclsp) ? inclstk_name[inclsp - 1] : fname_copy; if ((ctext) & (cmode)) { - flush_ins(); - comment(); - tab(); - tab(); - tab(); - tab(); - tab(); - tab(); - outstr(line); - nl(); + if (fexitlab) { + /* do not flush the instruction queue while compiling a function */ + /* instead put the comment inline with the queued instructions */ + char * temp = malloc(LINESIZE); + if (temp) { + memcpy(temp, line, LINESIZE); + out_ins_ex_arg(I_DEBUG, T_SOURCE_LINE, (intptr_t)temp, T_VALUE, line_number, filename); + } + } + else { + char * source; + flush_ins(); + ot(".dbg\tline,\t\""); + outstr(filename); + outstr("\", "); + outdec(line_number); + outstr("; "); + source = line; + while (source[0] == ' ' || source[0] == '\t') + ++source; + outstr(source); + nl(); + } } lptr = 0; return; @@ -233,13 +249,13 @@ void readline (void) } /* - * inbyte + * inbyte + * * Input : nothing * Output : int, (actualy char) * * Uses the preprocessor as much as possible to get readable data * then read the next char and make lptr points to the next one - * */ int inbyte (void) { @@ -253,13 +269,13 @@ int inbyte (void) } /* - * inchar + * inchar + * * Input : nothing * Output : int, (actualy char) * * Returns the current char, making lptr points to the next one * If the buffer if empty, fill it with next line from input - * */ int inchar (void) { @@ -272,14 +288,14 @@ int inchar (void) } /* - * gch + * gch + * * Input : nothing * Output : int, (actualy char) * * If the pointed char (by line and lptr) is 0, return this value * else return the current pointed char and advance the lptr to point * on the following char - * */ int gch (void) { @@ -290,14 +306,14 @@ int gch (void) } /* - * nch + * nch + * * Input : nothing * Output : int, (actualy char) * * If called when the pointed char is at the end of the line, return 0 * else return the following char * Doesn't change line nor lptr variable - * */ int nch (void) { @@ -308,7 +324,7 @@ int nch (void) } /* - * ch + * ch * * Input : nothing but use global line and lptr variables * Output : int, (actually char), corresponding to the current pointed char @@ -316,7 +332,6 @@ int nch (void) * * Appears to be the major function used during the parsing. * The global variables line and lptr aren't changed - * */ int ch (void) { @@ -324,11 +339,9 @@ int ch (void) } /* - * print a carriage return and a string only to console - * + * print a carriage return and a string only to console */ void pl (char *str) -/*char *str; */ { int k; @@ -339,10 +352,9 @@ void pl (char *str) } /* - * glabel - generate label + * glabel - generate label */ void glabel (char *lab) -/*char *lab;*/ { flush_ins(); /* David - optimize.c related */ prefix(); @@ -352,7 +364,7 @@ void glabel (char *lab) } /* - * gnlabel - generate numeric label + * gnlabel - generate numeric label */ void gnlabel (int nlab) { @@ -360,7 +372,7 @@ void gnlabel (int nlab) } /* - * Output internal generated label prefix + * Output internal generated label prefix */ void olprfix (void) { @@ -368,7 +380,7 @@ void olprfix (void) } /* - * Output a label definition terminator + * Output a label definition terminator */ void col (void) { @@ -376,8 +388,7 @@ void col (void) } /* - * begin a comment line for the assembler - * + * begin a comment line for the assembler */ void comment (void) { @@ -385,7 +396,7 @@ void comment (void) } /* - * Output a prefix in front of user labels + * Output a prefix in front of user labels */ void prefix (void) { @@ -393,12 +404,12 @@ void prefix (void) } /* - * tab + * tab + * * Input : nothing * Output : nothing * * Write a tab charater in the assembler file - * */ void tab (void) { @@ -406,28 +417,27 @@ void tab (void) } /* - * ol + * ol + * * Input : char* ptr * Output : nothing * * Writes the string ptr to the assembler file, preceded by a tab, ended by * a newline - * */ void ol (char *ptr) -/*char ptr[]; */ { ot(ptr); nl(); } /* - * ot + * ot + * * Input : char* ptr * Output : nothing * * Writes the string ptr to the assembler file, preceded by a tab - * */ void ot (char *ptr) /*char ptr[]; */ @@ -437,12 +447,12 @@ void ot (char *ptr) } /* - * nl + * nl + * * Input : nothing * Output : nothing * * Display a newline in the assembler file - * */ void nl (void) { @@ -450,12 +460,12 @@ void nl (void) } /* - * outsymbol + * outsymbol + * * Input : char* ptr * Output : nothing * * Writes the string ptr preceded with the result of the function prefix - * */ void outsymbol (SYMBOL *ptr) { @@ -473,7 +483,7 @@ void outsymbol (SYMBOL *ptr) } /* - * print specified number as label + * print specified number as label */ void outconst (int label) { @@ -482,7 +492,7 @@ void outconst (int label) } /* - * print specified number as label + * print specified number as label */ void outlabel (int label) { @@ -491,10 +501,10 @@ void outlabel (int label) } /* - * Output a decimal number to the assembler file + * Output a decimal number to the assembler file */ /* - void outdec (int number) +void outdec (int number) { int k, zs; char c; @@ -521,7 +531,9 @@ void outlabel (int label) } */ -/* Newer version, shorter and certainly faster */ +/* + * Newer version, shorter and certainly faster + */ void outdec (int number) { char s[16]; @@ -534,9 +546,8 @@ void outdec (int number) } /* - * Output an hexadecimal unsigned number to the assembler file + * Output an hexadecimal unsigned number to the assembler file */ - /* void outhex (int number) { @@ -563,7 +574,9 @@ void outdec (int number) } */ -/* Newer version, shorter and certainly faster */ +/* + * Newer version, shorter and certainly faster + */ void outhex (int number) { int i = 0; @@ -596,14 +609,13 @@ void outhexfix (int number, int length) outbyte(s[i++]); } - /* - * outbyte + * outbyte + * * Input : char c * Output : same as input, c * * if c is different of zero, write it to the output file - * */ char outbyte (char c) { @@ -615,12 +627,12 @@ char outbyte (char c) } /* - * outstr + * outstr + * * Input : char*, ptr * Output : nothing * * Send the input char* to the assembler file - * */ void outstr (const char *ptr) { @@ -631,12 +643,12 @@ void outstr (const char *ptr) } /* - * outlocal + * outlocal + * * Input : char* ptr * Output : nothing * * Writes the variable name as a comment - * */ void outlocal (SYMBOL *ptr) { diff --git a/src/hucc/main.c b/src/hucc/main.c index cc89b31a..447bf7a9 100644 --- a/src/hucc/main.c +++ b/src/hucc/main.c @@ -119,7 +119,7 @@ int main (int argc, char *argv[]) char *asmdefs_global_end; macptr = 0; - ctext = 0; + ctext = 1; argc--; argv++; errs = 0; sflag = 0; @@ -214,8 +214,14 @@ int main (int argc, char *argv[]) break; case 'g': - debug = 1; - strcat(asmdefs, "_DEBUG\t\t=\t1\n"); +// debug = 1; +// strcat(asmdefs, "_DEBUG\t\t=\t1\n"); + debug_info = toupper(*(p + 1)); + if (debug_info != 'C' && debug_info != 'A' && debug_info != 'L') + goto unknown_option; + p++; + if (debug_info == 'L') + verboseflag = 1; break; case 'l': @@ -296,8 +302,8 @@ int main (int argc, char *argv[]) } /* fallthrough */ case 'T': - ctext = 1; - fprintf(stderr, "\nwarning: Outputting C source to the listing file disables some optimizations!\n\n"); + /* accept this but ignore it */ +// ctext = 1; break; case 'v': @@ -320,7 +326,9 @@ int main (int argc, char *argv[]) usage(oldargv[0]); printf(HUC_VERSION); printf("\n"); - init_path(); + if (!init_path()) + exit(1); + /* Remember the first file, it will be used as the base for the output file name unless there is a user-specified outfile. */ p = pp = infiles[0]; @@ -426,6 +434,7 @@ int main (int argc, char *argv[]) // gtext (); parse(); fclose(input); + ol(".dbg\tclear"); // gdata (); dumplits(); dumpglbs(); @@ -477,28 +486,30 @@ void usage (char *exename) fprintf(stderr, "\n\n"); fprintf(stderr, "USAGE: %s [-options] infile\n", exename); fprintf(stderr, "\nCompiler options:\n"); - fprintf(stderr, "-Dsym[=val] define symbol 'sym' when compiling\n"); - fprintf(stderr, "-O[val] invoke optimization (level )\n"); - fprintf(stderr, "-fno-recursive optimize assuming non-recursive code\n"); - fprintf(stderr, "-fno-short-enums always use signed int for enums\n"); - fprintf(stderr, "-funsigned-char make \"char\" unsigned (the default)\n"); - fprintf(stderr, "-fsigned-char make \"char\" signed\n"); + fprintf(stderr, "-Dsym[=val] Define symbol 'sym' when compiling\n"); + fprintf(stderr, "-O[val] Invoke optimization (level )\n"); + fprintf(stderr, "-fno-recursive Optimize assuming non-recursive code\n"); + fprintf(stderr, "-fno-short-enums Always use signed int for enums\n"); + fprintf(stderr, "-funsigned-char Make \"char\" unsigned (the default)\n"); + fprintf(stderr, "-fsigned-char Make \"char\" signed\n"); fprintf(stderr, "\nOutput options:\n"); - fprintf(stderr, "-s/-S create asm output only (do not invoke assembler)\n"); + fprintf(stderr, "-s/-S Create asm output only (do not invoke assembler)\n"); fprintf(stderr, "\nLinker options:\n"); - fprintf(stderr, "-lname add library 'name.c' from include path\n"); - fprintf(stderr, "--cd create CD-ROM output\n"); - fprintf(stderr, "--scd create Super CD-ROM output\n"); - fprintf(stderr, "--acd create Arcade Card CD output\n"); - fprintf(stderr, "--sgx enable SuperGrafx support\n"); - fprintf(stderr, "--ted2 enable Turbo Everdrive2 support\n"); - fprintf(stderr, "--over(lay) create CD-ROM overlay section\n"); + fprintf(stderr, "-lname Add library 'name.c' from include path\n"); + fprintf(stderr, "--cd Create CD-ROM output\n"); + fprintf(stderr, "--scd Create Super CD-ROM output\n"); + fprintf(stderr, "--acd Create Arcade Card CD output\n"); + fprintf(stderr, "--sgx Enable SuperGrafx support\n"); + fprintf(stderr, "--ted2 Enable Turbo Everdrive2 support\n"); + fprintf(stderr, "--over(lay) Create CD-ROM overlay section\n"); fprintf(stderr, "\nAssembler options:\n"); - fprintf(stderr, "-Asym[=val] define symbol 'sym' to assembler\n"); + fprintf(stderr, "-Asym[=val] Define symbol 'sym' to assembler\n"); fprintf(stderr, "\nDebugging options:\n"); - fprintf(stderr, "-g enable extra debugging checks in output code\n"); - fprintf(stderr, "-t/-T include C source code in assembler output/listings\n"); - fprintf(stderr, "-v/-V increase verbosity of output files\n\n"); + fprintf(stderr, "-gC Output .SYM for mesen2 C source debugging\n"); + fprintf(stderr, "-gA Output .SYM for mesen2 ASM source debugging\n"); + fprintf(stderr, "-gL Output .SYM for mesen2 LST file debugging (the default)\n"); +// fprintf(stderr, "-g Enable extra debugging checks in output code\n"); + fprintf(stderr, "-v/-V Increase verbosity of output files\n\n"); exit(1); } @@ -1104,6 +1115,16 @@ int assemble (char *s) strcat_s(buf, sizeof(buf), "--hucc "); + if (debug_info) { + const char * debug_opt; + switch (debug_info) { + case 'C': debug_opt = "-gC "; break; + case 'A': debug_opt = "-gA "; break; + default: debug_opt = "-gL "; break; + } + strcat_s(buf, sizeof(buf), debug_opt); + } + strcat_s(buf, sizeof(buf), "\""); strcat_s(buf, sizeof(buf), s); buf[strlen(buf) - 1] = 's'; @@ -1155,6 +1176,14 @@ int assemble (char *s) opts[i++] = "--hucc"; /* --newproc --strip -O and more! */ + if (debug_info) { + switch (debug_info) { + case 'C': opts[i++] = "-gC"; break; + case 'A': opts[i++] = "-gA"; break; + default: opts[i++] = "-gL"; break; + } + } + strcpy(buf, s); buf[strlen(buf) - 1] = 's'; opts[i++] = buf; diff --git a/src/hucc/optimize.c b/src/hucc/optimize.c index cbbbab73..b7e88cea 100644 --- a/src/hucc/optimize.c +++ b/src/hucc/optimize.c @@ -47,11 +47,15 @@ unsigned char icode_flags[] = { 0, + // i-code for debug information + + /* I_DEBUG */ 0, + // i-code that retires the primary register contents /* I_FENCE */ 0, - /* i-code that declares a byte sized primary register */ + // i-code that declares a byte sized primary register /* I_SHORT */ 0, @@ -95,6 +99,7 @@ unsigned char icode_flags[] = { /* I_SWITCH_WR */ IS_USEPR, /* I_SWITCH_UR */ IS_USEPR, + /* I_DEFAULT */ 0, /* I_CASE */ 0, /* I_ENDCASE */ 0, /* I_LABEL */ 0, @@ -408,14 +413,11 @@ int compare2uchar [] = { CMP_UGE // CMP_UGE }; -/* defines */ -#define Q_SIZE 16 - -/* locals */ -static INS q_ins[Q_SIZE]; -static int q_rd; -static int q_wr; -static int q_nb; +/* instruction queue */ +INS q_ins[Q_SIZE]; +int q_rd; +int q_wr; +int q_nb; /* externs */ extern int arg_stack_flag; @@ -472,9 +474,11 @@ inline bool is_small_array (SYMBOL *sym) */ void push_ins (INS *ins) { -#ifdef DEBUG_OPTIMIZER - printf("\npush "); dump_ins(ins); -#endif + INS *p[Q_SIZE]; + int p_nb; + int i, j; + int remove = 0; + /* check queue size */ if (q_nb == Q_SIZE) { /* queue is full - flush the last instruction */ @@ -500,52 +504,73 @@ void push_ins (INS *ins) q_ins[q_wr] = *ins; + /* can't optimize a comment */ + if (ins->ins_code == I_DEBUG) + return; + +#ifdef DEBUG_OPTIMIZER + printf("\npush "); dump_ins(ins); +#endif + /* optimization level 1 - simple peephole optimizer, * replace known instruction patterns by highly * optimized asm code */ if (optimize >= 1) { - INS *p[Q_SIZE]; - int i, j; - int nb; - lv1_loop: - - - /* precalculate pointers to instructions */ - if (q_nb > 10) - nb = 10; - else - nb = q_nb; #ifdef DEBUG_OPTIMIZER printf("\nlv1_loop:\n"); #endif - i = 0; + + /* remove instructions from queue but preserve comments */ + if (remove) { + q_nb -= remove; + i = q_wr; + while (remove) { + if (q_ins[i].ins_code != I_DEBUG) + --remove; + if ((--i) < 0) + i += Q_SIZE; + } + j = i; + do { + if ((++j) >= Q_SIZE) + j -= Q_SIZE; + if (q_ins[j].ins_code == I_DEBUG) { + if ((++i) >= Q_SIZE) + i -= Q_SIZE; + memcpy(&q_ins[i], &q_ins[j], sizeof(INS)); + } + } while (j != q_wr); + q_wr = i; + } + + /* precalculate pointers to instructions */ + p_nb = 0; + i = q_nb; j = q_wr; - while (i < nb) { - /* save pointer */ - p[i] = &q_ins[j]; + while (i != 0 && p_nb < 6) { + if (q_ins[j].ins_code != I_DEBUG) { #ifdef DEBUG_OPTIMIZER - printf("%d ", i); dump_ins(p[i]); + printf("%d ", p_nb); dump_ins(&q_ins[j]); #endif - /* next */ - j -= 1; - if (j < 0) + p[p_nb++] = &q_ins[j]; + } + --i; + if ((--j) < 0) j += Q_SIZE; - - ++i; } + remove = 0; /* LEVEL 1 - FUN STUFF STARTS HERE */ - nb = 0; /* ********************************************************* */ /* ********************************************************* */ /* first check for I_FENCE, and remove it ASAP */ - if (q_nb >= 1 && p[0]->ins_code == I_FENCE) { + if (p_nb >= 1 && p[0]->ins_code == I_FENCE) { /* remove I_FENCE after it has been checked */ - nb = 1; + remove = 1; /* * __ld.wi i --> __st.{w/u}miq symbol, i @@ -557,7 +582,7 @@ void push_ins (INS *ins) * __fence */ if - ((q_nb >= 3) && + ((p_nb >= 3) && (p[1]->ins_code == I_ST_WM || p[1]->ins_code == I_ST_UM || p[1]->ins_code == X_ST_WS || @@ -577,7 +602,7 @@ void push_ins (INS *ins) } p[2]->imm_type = T_VALUE; p[2]->imm_data = data; - nb = 2; + remove = 2; } /* @@ -588,12 +613,12 @@ void push_ins (INS *ins) * __fence */ else if - ((q_nb >= 2) && + ((p_nb >= 2) && (p[1]->ins_code == I_ADD_WI || p[1]->ins_code == I_SUB_WI || p[1]->ins_code == I_GETACC) ) { - nb = 2; + remove = 2; } /* @@ -607,7 +632,7 @@ void push_ins (INS *ins) * unused pre-decrement or post-decrement value */ else if - ((q_nb >= 2) && + ((p_nb >= 2) && (p[1]->ins_code == X_INCLD_WM || p[1]->ins_code == X_INCLD_BM || p[1]->ins_code == X_INCLD_UM || @@ -701,30 +726,21 @@ void push_ins (INS *ins) case X_LDDEC_UAY: p[1]->ins_code = X_DEC_UAYQ; break; default: abort(); } - nb = 1; + remove = 1; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } /* ********************************************************* */ /* ********************************************************* */ /* then check for I_SHORT, and remove it ASAP */ - if (q_nb >= 1 && p[0]->ins_code == I_SHORT) { + if (p_nb >= 1 && p[0]->ins_code == I_SHORT) { /* remove I_SHORT after it has been checked */ - nb = 1; + remove = 1; /* * __ld.wi i --> __ld.uiq i @@ -737,7 +753,7 @@ void push_ins (INS *ins) * __short */ if - ((q_nb >= 2) && + ((p_nb >= 2) && (p[1]->ins_code == I_LD_WI || p[1]->ins_code == I_LD_WM || p[1]->ins_code == I_LD_BM || @@ -756,28 +772,19 @@ void push_ins (INS *ins) case X_LD_US: p[1]->ins_code = X_LD_USQ; break; default: abort(); } - nb = 1; + remove = 1; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } /* ********************************************************* */ /* then evaluate constant expressions */ /* ********************************************************* */ - if (q_nb >= 3) { + if (p_nb >= 3) { /* * __push.wr --> __add.wi i * __ld.wi i @@ -858,7 +865,7 @@ void push_ins (INS *ins) case I_UMOD_WT: p[2]->ins_code = I_UMOD_WI; break; default: abort(); } - nb = 2; + remove = 2; if (p[2]->ins_type == T_VALUE && p[2]->ins_data == 0) { switch (p[2]->ins_code) { @@ -873,27 +880,18 @@ void push_ins (INS *ins) p[2]->ins_code = I_LD_WI; break; default: - nb = 3; + remove = 3; break; } } } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } - if (q_nb >= 2) { + if (p_nb >= 2) { /* * __ld.wi i --> __ld.wi (~i) * __com.wr @@ -905,7 +903,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data = ~p[1]->ins_data; - nb = 1; + remove = 1; } /* @@ -919,7 +917,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data = -p[1]->ins_data; - nb = 1; + remove = 1; } /* @@ -934,7 +932,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data += p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -949,7 +947,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data -= p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -964,7 +962,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data &= p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -979,7 +977,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data ^= p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -994,7 +992,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data |= p[0]->ins_data; - nb = 1; + remove = 1; } @@ -1009,7 +1007,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data += p[1]->ins_data; - nb = 1; + remove = 1; } /* @@ -1024,7 +1022,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data <<= p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -1039,7 +1037,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data >>= p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -1054,7 +1052,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data = ((uintptr_t) p[1]->ins_data) >> p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -1069,7 +1067,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data *= p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -1084,7 +1082,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data = p[1]->ins_data / p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -1099,7 +1097,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data = ((unsigned) p[1]->ins_data) / ((unsigned) p[0]->ins_data); - nb = 1; + remove = 1; } /* @@ -1114,7 +1112,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data = p[1]->ins_data % p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -1129,28 +1127,19 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data = ((unsigned) p[1]->ins_data) % ((unsigned) p[0]->ins_data); - nb = 1; + remove = 1; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } /* ********************************************************* */ /* then transform muliplication and division by a power of 2 */ /* ********************************************************* */ - if (q_nb >= 1) { + if (p_nb >= 1) { /* * __mul.wi i --> __asl.wi log2(i) */ @@ -1176,7 +1165,7 @@ void push_ins (INS *ins) } else if (p[0]->ins_data == 1) { - nb = 1; + remove = 1; } else if (__builtin_popcount((unsigned int)p[0]->ins_data) == 1) { @@ -1195,7 +1184,7 @@ void push_ins (INS *ins) * * N.B. You cannot convert __sdiv.wi into __asr.wi! */ - if + else if ((p[0]->ins_code == I_UDIV_WI || p[0]->ins_code == I_UDIV_UI) && (p[0]->ins_type == T_VALUE) && @@ -1208,7 +1197,7 @@ void push_ins (INS *ins) } else if (p[0]->ins_data == 1) { - nb = 1; + remove = 1; } else if (__builtin_popcount((unsigned int)p[0]->ins_data) == 1) { @@ -1227,7 +1216,7 @@ void push_ins (INS *ins) * * N.B. Modifying an __smod.wi is ugly! */ - if + else if ((p[0]->ins_code == I_UMOD_WI || p[0]->ins_code == I_UMOD_UI) && (p[0]->ins_type == T_VALUE) && @@ -1255,25 +1244,16 @@ void push_ins (INS *ins) } } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } /* ********************************************************* */ /* then optimize conditional tests */ /* ********************************************************* */ - if (q_nb >= 4) { + if (p_nb >= 4) { /* * is_ubyte() --> is_ubyte() * __push.wr __cmp.umq type, symbol @@ -1300,7 +1280,7 @@ void push_ins (INS *ins) default: break; } p[2]->cmp_type = compare2uchar[p[0]->cmp_type]; - nb = 2; + remove = 2; } /* @@ -1320,7 +1300,7 @@ void push_ins (INS *ins) ) { *p[1] = *p[2]; *p[2] = *p[0]; - nb = 1; + remove = 1; } /* @@ -1346,7 +1326,7 @@ void push_ins (INS *ins) (p[3]->ins_code == I_LABEL) ) { *p[2] = *p[0]; - nb = 2; + remove = 2; } /* @@ -1374,24 +1354,15 @@ void push_ins (INS *ins) ) { *p[1] = *p[0]; p[2]->ins_code = X_NOT_CF; - nb = 1; + remove = 1; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } - if (q_nb >= 3) { + if (p_nb >= 3) { /* * __push.wr --> __not.wr * __ld.wi 0 @@ -1416,7 +1387,7 @@ void push_ins (INS *ins) p[2]->ins_code = (p[0]->cmp_type == CMP_EQU) ? I_NOT_WR : I_TST_WR; p[2]->ins_type = 0; p[2]->ins_data = 0; - nb = 2; + remove = 2; } /* @@ -1448,7 +1419,7 @@ void push_ins (INS *ins) default: break; } p[2]->cmp_type = p[0]->cmp_type; - nb = 2; + remove = 2; } /* @@ -1495,7 +1466,7 @@ void push_ins (INS *ins) p[2]->ins_code == X_CMP_USQ) ) { p[2]->cmp_type = compare2not[p[2]->cmp_type]; - nb = 2; + remove = 2; } /* @@ -1608,7 +1579,7 @@ void push_ins (INS *ins) case X_TAND_WI: p[2]->ins_code = X_NAND_WI; break; default: abort(); } - nb = 2; + remove = 2; } /* @@ -1733,24 +1704,15 @@ void push_ins (INS *ins) p[2]->ins_code == X_TST_UAY || p[2]->ins_code == X_TAND_WI) ) { - nb = 2; + remove = 2; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } - if (q_nb >= 2) { + if (p_nb >= 2) { /* * __ld.{w/b/u}p --> __tst.{w/u}p * __tst.wr @@ -1851,7 +1813,7 @@ void push_ins (INS *ins) default: abort(); } } - nb = 1; + remove = 1; } /* @@ -1913,7 +1875,7 @@ void push_ins (INS *ins) (p[0]->ins_code == I_BOOLEAN) ) { *p[1] = *p[0]; - nb = 1; + remove = 1; } /* @@ -1924,25 +1886,7 @@ void push_ins (INS *ins) ((p[0]->ins_code == I_BRA) && (p[1]->ins_code == I_BRA) ) { - nb = 1; - } - - /* - * LLaa: LLaa .alias LLbb - * __bra LLbb --> __bra LLbb - */ - else if - ((p[0]->ins_code == I_BRA) && - (p[1]->ins_code == I_LABEL) - ) { - int i = 1; - do { - if (p[i]->ins_data != p[0]->ins_data) { - p[i]->ins_code = I_ALIAS; - p[i]->imm_type = T_VALUE; - p[i]->imm_data = p[0]->ins_data; - } - } while (++i < q_nb && i < 10 && p[i]->ins_code == I_LABEL); + remove = 1; } /* @@ -1956,28 +1900,45 @@ void push_ins (INS *ins) (p[0]->ins_data == p[1]->ins_data) ) { *p[1] = *p[0]; - nb = 1; + remove = 1; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; + /* + * LLaa: LLaa .alias LLbb + * __bra LLbb --> __bra LLbb + */ + else if + ((p[0]->ins_code == I_BRA) && + (p[1]->ins_code == I_LABEL) + ) { + int i = q_nb; + int j = q_wr; + while (--i) { + if ((--j) < 0) + j += Q_SIZE; + if (q_ins[j].ins_code == I_LABEL) { + if (q_ins[j].ins_data != p[0]->ins_data) { + q_ins[j].ins_code = I_ALIAS; + q_ins[j].imm_type = T_VALUE; + q_ins[j].imm_data = p[0]->ins_data; + } + } + else + if (q_ins[j].ins_code != I_DEBUG) + break; + } + } - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } /* ********************************************************* */ /* 4-instruction patterns */ /* ********************************************************* */ - if (q_nb >= 4) { + if (p_nb >= 4) { /* __ld.wi i --> __ld.wi i * __push.wr __push.wr * __st.wm __ptr __ld.{w/u}m i @@ -2006,7 +1967,7 @@ void push_ins (INS *ins) p[1]->ins_code = I_LD_BM; else p[1]->ins_code = I_LD_UM; - nb = 1; + remove = 1; } /* @@ -2039,7 +2000,7 @@ void push_ins (INS *ins) else p[1]->ins_code = X_LD_US; p[1]->ins_data += 2; - nb = 1; + remove = 1; } /* @@ -2061,7 +2022,7 @@ void push_ins (INS *ins) /* replace code */ p[3]->ins_code = I_LEA_S; p[3]->ins_data += p[1]->ins_data; - nb = 3; + remove = 3; } #if OPT_ARRAY_RD @@ -2089,34 +2050,29 @@ void push_ins (INS *ins) p[3]->ins_code = X_LD_WAR; p[3]->ins_type = T_SYMBOL; p[3]->ins_data = p[2]->ins_data; - nb = 3; + remove = 3; } #endif - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } /* ********************************************************* */ /* 3-instruction patterns */ /* ********************************************************* */ - if (q_nb >= 3) { + if (p_nb >= 3) { /* * __case --> LLnn: * __endcase * LLnn: * + * __default --> LLnn: + * __endcase + * LLnn: + * * I_ENDCASE is only generated in order to catch which * case statements could fall through to the next case * so that an SAX instruction could be generated if or @@ -2128,11 +2084,12 @@ void push_ins (INS *ins) if ((p[0]->ins_code == I_LABEL) && (p[1]->ins_code == I_ENDCASE) && - (p[2]->ins_code == I_CASE) + (p[2]->ins_code == I_CASE || + p[2]->ins_code == I_DEFAULT) ) { /* remove code */ *p[2] = *p[0]; - nb = 2; + remove = 2; } /* __ld.wi i --> __ld.{w/b/u}m i @@ -2158,7 +2115,7 @@ void push_ins (INS *ins) p[2]->ins_code = I_LD_BM; else p[2]->ins_code = I_LD_UM; - nb = 2; + remove = 2; } /* @@ -2185,7 +2142,7 @@ void push_ins (INS *ins) p[2]->ins_code = X_LD_BS; else p[2]->ins_code = X_LD_US; - nb = 2; + remove = 2; } /* @@ -2218,7 +2175,7 @@ void push_ins (INS *ins) case I_OR_WT: p[2]->ins_code = I_OR_WM; break; default: abort(); } - nb = 2; + remove = 2; } /* @@ -2251,7 +2208,7 @@ void push_ins (INS *ins) case I_OR_WT: p[2]->ins_code = I_OR_UM; break; default: abort(); } - nb = 2; + remove = 2; } /* @@ -2273,7 +2230,7 @@ void push_ins (INS *ins) default: abort(); } p[2]->ins_data -= 2; - nb = 2; + remove = 2; } /* @@ -2309,7 +2266,7 @@ void push_ins (INS *ins) case I_LD_UM: p[2]->ins_code = (p[1]->ins_code == I_ADD_WI) ? X_INCLD_UM : X_DECLD_UM; break; default: break; } - nb = 2; + remove = 2; } /* @@ -2344,7 +2301,7 @@ void push_ins (INS *ins) case X_LD_US: p[2]->ins_code = (p[1]->ins_code == I_ADD_WI) ? X_INCLD_US : X_DECLD_US; break; default: break; } - nb = 2; + remove = 2; } /* @@ -2392,7 +2349,7 @@ void push_ins (INS *ins) case X_LDP_UAY: p[2]->ins_code = (p[1]->ins_code == I_ADD_WI) ? X_INCLD_UAY : X_DECLD_UAY; break; default: break; } - nb = 2; + remove = 2; } #if OPT_ARRAY_RD @@ -2417,7 +2374,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[2]->ins_code = (p[0]->ins_code == I_LD_BP) ? X_LD_BAR : X_LD_UAR; - nb = 2; + remove = 2; } #endif @@ -2448,7 +2405,7 @@ void push_ins (INS *ins) p[2]->ins_code = X_LDP_WAR; else p[2]->ins_code = (p[0]->ins_code == I_LD_BP) ? X_LDP_BAR : X_LDP_UAR; - nb = 2; + remove = 2; } #endif @@ -2511,28 +2468,19 @@ void push_ins (INS *ins) case X_NOT_UAY: p[2]->ins_code = X_BOOLNOT_UAY; break; default: abort(); } - nb = 1; + remove = 1; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } /* ********************************************************* */ /* 2-instruction patterns */ /* ********************************************************* */ - if (q_nb >= 2) { + if (p_nb >= 2) { /* * __ld.{b/u}p __ptr --> __ld.{b/u}p __ptr * __switch.wr __switch.ur @@ -2559,7 +2507,7 @@ void push_ins (INS *ins) ) { /* optimize code */ p[0]->ins_code = I_SWITCH_UR; - nb = 0; + remove = 0; } /* @@ -2583,7 +2531,7 @@ void push_ins (INS *ins) p[1]->ins_code == I_BRA) ) { /* remove code */ - nb = 1; + remove = 1; } /* @@ -2599,7 +2547,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data += p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -2617,7 +2565,7 @@ void push_ins (INS *ins) /* replace code */ p[1]->ins_code = I_LEA_S; p[1]->ins_data += p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -2632,7 +2580,7 @@ void push_ins (INS *ins) ) { /* replace code */ p[1]->ins_data += p[0]->ins_data; - nb = 1; + remove = 1; } /* @@ -2663,7 +2611,7 @@ void push_ins (INS *ins) p[1]->ins_code = I_ASL_WI; p[1]->ins_type = T_VALUE; p[1]->ins_data = data; - nb = 1; + remove = 1; } /* @@ -2691,7 +2639,7 @@ void push_ins (INS *ins) p[1]->ins_type = T_SYMBOL; p[1]->ins_data = (intptr_t)newsym; } - nb = 1; + remove = 1; } /* @@ -2718,7 +2666,7 @@ void push_ins (INS *ins) *p[1] = *p[0]; p[1]->ins_code = I_LD_WI; } - nb = 1; + remove = 1; } /* @@ -2731,7 +2679,7 @@ void push_ins (INS *ins) (cmp_operands(p[0], p[1]) == 1) ) { /* remove code */ - nb = 1; + remove = 1; } /* @@ -2743,7 +2691,7 @@ void push_ins (INS *ins) (p[1]->ins_code == X_ST_WS) && (p[0]->ins_data == p[1]->ins_data)) { /* remove code */ - nb = 1; + remove = 1; } /* @@ -2793,7 +2741,7 @@ void push_ins (INS *ins) ) { /* remove code */ *p[1] = *p[0]; - nb = 1; + remove = 1; } /* @@ -2842,7 +2790,7 @@ void push_ins (INS *ins) case X_DECLD_UAY: p[1]->ins_code = X_LDDEC_UAY; break; default: break; } - nb = 1; + remove = 1; } /* @@ -2891,7 +2839,7 @@ void push_ins (INS *ins) case X_INCLD_UAY: p[1]->ins_code = X_LDINC_UAY; break; default: break; } - nb = 1; + remove = 1; } /* @@ -2937,7 +2885,7 @@ void push_ins (INS *ins) case X_LD_US: p[1]->ins_code = X_LD_USQ; break; default: break; } - nb = 0; + remove = 0; } /* @@ -2976,7 +2924,7 @@ void push_ins (INS *ins) case X_LDP_UAR: p[0]->ins_code = X_LDP_UAY; break; default: break; } - nb = 0; + remove = 0; } /* @@ -3018,7 +2966,7 @@ void push_ins (INS *ins) case X_LDP_UAR: p[0]->ins_code = X_LDP_UAY; break; default: break; } - nb = 0; + remove = 0; } /* @@ -3068,7 +3016,7 @@ void push_ins (INS *ins) p[1]->ins_code = I_LD_WI; p[1]->ins_type = T_VALUE; p[1]->ins_data = 0; - nb = 1; + remove = 1; } else { p[0]->ins_code = I_LSR_UIQ; /* no instructions removed, just loop */ @@ -3096,25 +3044,16 @@ void push_ins (INS *ins) goto lv1_loop; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } /* ********************************************************* */ /* 1-instruction patterns */ /* ********************************************************* */ - if (q_nb >= 1) { + if (p_nb >= 1) { /* * __add.wi 0 --> * @@ -3131,21 +3070,12 @@ void push_ins (INS *ins) (p[0]->ins_type == T_VALUE) && (p[0]->ins_data == 0) ) { - nb = 1; + remove = 1; } - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv1_loop; - } } } @@ -3448,23 +3378,47 @@ void push_ins (INS *ins) /* * optimization level 2b - after the instruction re-scheduler */ - if (q_nb >= 3) { - INS *p[3]; - int i, j; - int nb = 0; lv2_loop: - /* precalculate pointers to instructions */ - for (i = 0, j = q_wr; i < 3; i++) { - /* save pointer */ - p[i] = &q_ins[j]; + /* remove instructions from queue but preserve comments */ + if (remove) { + q_nb -= remove; + i = q_wr; + while (remove) { + if (q_ins[i].ins_type != I_DEBUG) + --remove; + if ((--i) < 0) + i += Q_SIZE; + } + j = i; + do { + if ((++j) >= Q_SIZE) + j -= Q_SIZE; + if (q_ins[j].ins_type == I_DEBUG) { + if ((++i) >= Q_SIZE) + i -= Q_SIZE; + memcpy(&q_ins[i], &q_ins[j], sizeof(INS)); + } + } while (j != q_wr); + q_wr = i; + } - /* next */ - j -= 1; - if (j < 0) - j += Q_SIZE; + /* precalculate pointers to instructions */ + p_nb = 0; + i = q_nb; + j = q_wr; + while (i != 0 && p_nb < 3) { + if (q_ins[j].ins_type != I_DEBUG) { + p[p_nb++] = &q_ins[j]; } + --i; + --j; + if ((--j) < 0) + j += Q_SIZE; + } + remove = 0; + if (p_nb >= 3) { /* * __push.wr --> __st.{w/u}pi i * __ld.wi i @@ -3485,7 +3439,7 @@ void push_ins (INS *ins) /* replace code */ p[2]->ins_code = p[0]->ins_code == I_ST_WPT ? I_ST_WPI : I_ST_UPI; p[2]->ins_data = p[1]->ins_data; - nb = 2; + remove = 2; } #if 0 @@ -3519,18 +3473,9 @@ void push_ins (INS *ins) } #endif - /* flush queue */ - if (nb) { - q_wr -= nb; - q_nb -= nb; - nb = 0; - - if (q_wr < 0) - q_wr += Q_SIZE; - - /* loop */ + /* remove instructions from queue and begin again */ + if (remove) goto lv2_loop; - } } } } diff --git a/src/hucc/optimize.h b/src/hucc/optimize.h index 281aa502..41ae43eb 100644 --- a/src/hucc/optimize.h +++ b/src/hucc/optimize.h @@ -17,6 +17,15 @@ /* flag information for each of the i-code instructions */ extern unsigned char icode_flags[]; +/* defines */ +#define Q_SIZE 32 + +/* instruction queue */ +extern INS q_ins[Q_SIZE]; +extern int q_rd; +extern int q_wr; +extern int q_nb; + void push_ins (INS *ins); void flush_ins (void); void flush_ins_label (int nextlabel); diff --git a/src/hucc/preproc.c b/src/hucc/preproc.c index 6321550d..9004ff1c 100644 --- a/src/hucc/preproc.c +++ b/src/hucc/preproc.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "code.h" #include "defs.h" #include "data.h" @@ -28,11 +30,13 @@ #define PATH_SEPARATOR ';' #define DIR_SEPARATOR '\\' #define DIR_SEPARATOR_STRING "\\" +#define BAD_SEPARATOR '/' #define DEFAULT_DIRS "c:\\huc\\include\\hucc" #else #define PATH_SEPARATOR ':' #define DIR_SEPARATOR '/' #define DIR_SEPARATOR_STRING "/" +#define BAD_SEPARATOR '\\' #define DEFAULT_DIRS "/usr/local/lib/huc/include/hucc:" \ "/usr/local/huc/include/hucc:" \ "/usr/local/share/huc/include/hucc:" \ @@ -42,8 +46,11 @@ "/usr/include/hucc" #endif +#define MAX_PATHS 16 + /* locals */ -static char *incpath[10]; +static char *curpath; +static char *incpath[MAX_PATHS] = { "" }; static const char *include_path (void) { @@ -63,14 +70,19 @@ char **include_dirs (void) /* * init the include paths */ -void init_path (void) +int init_path (void) { const char *p, *pl; int i, l; + if ((curpath = getcwd(NULL, 0)) == NULL || curpath[0] == '(') { + fprintf(stderr, "Unable to get the current directory name\n"); + return (NO); + } + p = include_path(); - for (i = 0; i < 10; i++) { + for (i = 1; i < MAX_PATHS; i++) { pl = strchr(p, PATH_SEPARATOR); if (pl == NULL) @@ -96,24 +108,43 @@ void init_path (void) incpath[i] = 0; } } + return (YES); } /* * open a file - browse paths */ -FILE *file_open (char *name, char *mode) +FILE *file_open (char *name, int initial_path) { FILE *fp = NULL; - char testname[256]; + char testname[FILENAMESIZE]; + char *p; int i; - for (i = 0; i < 10; i++) { - if (incpath[i] && strlen(incpath[i])) { + for (i = initial_path; i < MAX_PATHS; i++) { + if (incpath[i]) { + if (incpath[i][0] != '\0') { + if (name[0] == DIR_SEPARATOR || name[0] == BAD_SEPARATOR) + break; +#ifdef _WIN32 + if (isalpha(name[0]) && name[1] == ':') + break; +#endif + } + if ((strlen(incpath[i]) + strlen(name)) >= FILENAMESIZE) { + fprintf(stderr, "%s: include path + filename is too long!\n", name); + break; + } strcpy(testname, incpath[i]); strcat(testname, name); - strcpy(inclstk_name[inclsp], testname); - fp = fopen(testname, mode); - if (fp != NULL) break; + p = testname; + while ((p = strchr(p, BAD_SEPARATOR)) != NULL) + *p++ = DIR_SEPARATOR; + fp = fopen(testname, "r"); + if (fp != NULL) { + strcpy(inclstk_name[inclsp], testname); + break; + } } } @@ -134,7 +165,7 @@ void doinclude (void) FILE *inp2; blanks(); - inp2 = fixiname(); + inp2 = open_include(); if (inp2) { if (inclsp < INCLSIZ) { inclstk_line[inclsp] = line_number; @@ -152,6 +183,9 @@ void doinclude (void) kill(); } +/* + * open auto-include file "globals.h" + */ void incl_globals_h (void) { FILE *inp2; @@ -159,8 +193,7 @@ void incl_globals_h (void) /* open the globals.h file to include those variables */ /* but if we can't open it, it's no problem */ - if ((inp2 = fopen("globals.h", "r")) == NULL) - inp2 = file_open("globals.h", "r"); + inp2 = file_open("globals.h", 0); if (inp2) { if (inclsp < INCLSIZ) { @@ -169,7 +202,6 @@ void incl_globals_h (void) #endif inclstk_line[inclsp] = line_number; line_number = 0; - strcpy(inclstk_name[inclsp], "globals.h"); inclstk[inclsp++] = input2; input2 = inp2; globals_h_in_process = 1; @@ -181,6 +213,9 @@ void incl_globals_h (void) } } +/* + * open auto-include file "huc.h" + */ void incl_huc_h (void) { FILE *inp2; @@ -188,8 +223,7 @@ void incl_huc_h (void) /* open the huc.h file to include those variables */ /* but if we can't open it, it's no problem */ - if ((inp2 = fopen("huc.h", "r")) == NULL) - inp2 = file_open("huc.h", "r"); + inp2 = file_open("huc.h", 0); if (inp2) { if (inclsp < INCLSIZ) { @@ -198,7 +232,6 @@ void incl_huc_h (void) #endif inclstk_line[inclsp] = line_number; line_number = 0; - strcpy(inclstk_name[inclsp], "huc.h"); inclstk[inclsp++] = input2; input2 = inp2; } @@ -210,12 +243,12 @@ void incl_huc_h (void) } /* - * fixiname - remove "brackets" around include file name + * open_include - remove "brackets" around include file name */ -FILE *fixiname (void) +FILE *open_include (void) { char c1, c2, *p, *ibp; - char buf[LINESIZE]; + char buf[FILENAMESIZE]; FILE *fp; ibp = &buf[0]; @@ -225,22 +258,23 @@ FILE *fixiname (void) error("incorrect file name delimiter"); return (NULL); } - for (p = line + lptr; *p;) { + for (p = line + lptr; *p && (ibp - buf) < FILENAMESIZE;) { if (*p == c2) break; if ((*p == '\\') && (p[1] == '\\')) p++; *ibp++ = *p++; } + if ((ibp - buf) == FILENAMESIZE) { + error("file name too long"); + return (NULL); + } if (*p != c2) { error("file name delimiter missing"); return (NULL); } *ibp = 0; - fp = NULL; - strcpy(inclstk_name[inclsp], buf); - if ((c1 == '<') || ((fp = fopen(buf, "r")) == NULL)) - fp = file_open(buf, "r"); + fp = file_open(buf, (c1 == '<')); #ifdef DEBUG_PREPROC if (fp) { printf("HuCC opening #include \"%s\".\n", buf); @@ -258,10 +292,12 @@ FILE *fixiname (void) */ void doasm (void) { + char * source; /* Save the SP if this #asm section is inside a function */ if (fexitlab) out_ins(I_SAVESP, 0, 0); flush_ins(); /* David - optimize.c related */ + ol(".dbg\tclear"); cmode = 0; FOREVER { readline(); @@ -269,16 +305,36 @@ void doasm (void) break; if (feof(input)) break; +#if 1 + source = line; + if (source[0] == ' ' || source[0] == '\t') { + while (source[0] == ' ' || source[0] == '\t') + ++source; + tab(); + tab(); + } + outstr(source); +#else outstr(line); +#endif nl(); } - kill(); - cmode = 1; /* Restore the SP if this #asm section is inside a function */ if (fexitlab) { out_ins(I_LOADSP, 0, 0); - flush_ins(); /* David - optimize.c related */ } + /* Mark the end of the #asm section */ + if (ctext) { + char * temp = malloc(LINESIZE); + char * filename = (inclsp) ? inclstk_name[inclsp - 1] : fname_copy; + if (temp) { + memcpy(temp, line, LINESIZE); + out_ins_ex_arg(I_DEBUG, T_SOURCE_LINE, (intptr_t)temp, T_VALUE, line_number, filename); + } + } + flush_ins(); /* David - optimize.c related */ + kill(); + cmode = 1; } void doasmdef (void) @@ -612,7 +668,7 @@ int cpp (int subline) parg[0] = c; parg[1] = '\0'; if (++parg >= pend) { - error("macro argument too int"); + error("macro argument too long"); return (0); } if (ch() == ')') { @@ -681,7 +737,7 @@ int cpp (int subline) } keepch(0); if (mptr >= MPMAX) - error("line too int"); + error("line too long"); /* copy cooked input back to where we got the raw input from */ strcpy(&line[llptr], mline); /* ...and continue processing at that point */ diff --git a/src/hucc/preproc.h b/src/hucc/preproc.h index f7044a07..a83299b0 100644 --- a/src/hucc/preproc.h +++ b/src/hucc/preproc.h @@ -7,9 +7,11 @@ void incl_globals_h (void); void incl_huc_h (void); -FILE *fixiname (void); +FILE *open_include (void); -void init_path (void); +int init_path (void); + +FILE *file_open (char *name, int initial_path); void doasmdef (void); diff --git a/src/hucc/primary.c b/src/hucc/primary.c index fae91cc7..22c5a742 100644 --- a/src/hucc/primary.c +++ b/src/hucc/primary.c @@ -447,9 +447,9 @@ int constant (int *val) { if (number(val)) immed(T_VALUE, *val); - else if (pstr(val)) + else if (quoted_chr(val)) immed(T_VALUE, *val); - else if (qstr(val)) { + else if (quoted_str(val)) { immed(T_STRING, *val); return (2); } @@ -507,7 +507,7 @@ bool number (int *val) return (true); } -static int parse0 (int *num) +static int parse_const0 (int *num) { if (!const_expr(num, ")", NULL)) return (0); @@ -517,7 +517,7 @@ static int parse0 (int *num) return (1); } -static int parse3 (int *num) +static int parse_const3 (int *num) { int num2; struct type_type t; @@ -549,9 +549,9 @@ static int parse3 (int *num) else op = 0; - if (!(have_paren && parse0(&num2)) && + if (!(have_paren && parse_const0(&num2)) && !number(&num2) && - !pstr(&num2) && + !quoted_chr(&num2) && !(symname(n) && find_enum(n, &num2))) return (0); @@ -590,11 +590,11 @@ static int parse3 (int *num) return (1); } -static int parse5 (int *num) +static int parse_const5 (int *num) { int num1, num2; - if (!parse3(&num1)) + if (!parse_const3(&num1)) return (0); for (;;) { @@ -603,26 +603,30 @@ static int parse5 (int *num) op = '*'; else if (match("/")) op = '/'; + else if (match("%")) + op = '%'; else { *num = num1; return (1); } - if (!parse3(&num2)) + if (!parse_const3(&num2)) return (0); if (op == '*') num1 *= num2; - else + else if (op == '/') num1 /= num2; + else + num1 %= num2; } } -static int parse6 (int *num) +static int parse_const6 (int *num) { int num1, num2; - if (!parse5(&num1)) + if (!parse_const5(&num1)) return (0); for (;;) { @@ -636,7 +640,7 @@ static int parse6 (int *num) return (1); } - if (!parse5(&num2)) + if (!parse_const5(&num2)) return (0); if (op == '-') @@ -646,11 +650,11 @@ static int parse6 (int *num) } } -static int parse7 (int *num) +static int parse_const7 (int *num) { int num1, num2; - if (!parse6(&num1)) + if (!parse_const6(&num1)) return (0); for (;;) { @@ -664,7 +668,7 @@ static int parse7 (int *num) return (1); } - if (!parse6(&num2)) + if (!parse_const6(&num2)) return (0); if (op == 'l') @@ -674,11 +678,45 @@ static int parse7 (int *num) } } -static int parse9 (int *num) +static int parse_const8 (int *num) { int num1, num2; - if (!parse7(&num1)) + if (!parse_const7(&num1)) + return (0); + + for (;;) { + char op; + if (match("<=")) + op = 0; + else if (match(">=")) + op = 1; + else if (match("<")) + op = 2; + else if (match(">")) + op = 3; + else { + *num = num1; + return (1); + } + + if (!parse_const7(&num2)) + return (0); + + switch (op) { + case 0: num1 = (num1 <= num2); break; + case 1: num1 = (num1 >= num2); break; + case 2: num1 = (num1 < num2); break; + case 3: num1 = (num1 > num2); break; + } + } +} + +static int parse_const9 (int *num) +{ + int num1, num2; + + if (!parse_const8(&num1)) return (0); for (;;) { @@ -692,7 +730,7 @@ static int parse9 (int *num) return (1); } - if (!parse7(&num2)) + if (!parse_const8(&num2)) return (0); if (op == '=') @@ -702,9 +740,109 @@ static int parse9 (int *num) } } +static int parse_const10 (int *num) +{ + int num1, num2; + + if (!parse_const9(&num1)) + return (0); + + for (;;) { + if (!match("&")) { + *num = num1; + return (1); + } + + if (!parse_const9(&num2)) + return (0); + + num1 = num1 & num2; + } +} + +static int parse_const11 (int *num) +{ + int num1, num2; + + if (!parse_const10(&num1)) + return (0); + + for (;;) { + if (!match("^")) { + *num = num1; + return (1); + } + + if (!parse_const10(&num2)) + return (0); + + num1 = num1 ^ num2; + } +} + +static int parse_const12 (int *num) +{ + int num1, num2; + + if (!parse_const11(&num1)) + return (0); + + for (;;) { + if (!match("|")) { + *num = num1; + return (1); + } + + if (!parse_const11(&num2)) + return (0); + + num1 = num1 | num2; + } +} + +static int parse_const13 (int *num) +{ + int num1, num2; + + if (!parse_const12(&num1)) + return (0); + + for (;;) { + if (!match("&&")) { + *num = num1; + return (1); + } + + if (!parse_const12(&num2)) + return (0); + + num1 = num1 && num2; + } +} + +static int parse_const14 (int *num) +{ + int num1, num2; + + if (!parse_const13(&num1)) + return (0); + + for (;;) { + if (!match("||")) { + *num = num1; + return (1); + } + + if (!parse_const13(&num2)) + return (0); + + num1 = num1 || num2; + } +} + bool const_expr (int *num, char *end1, char *end2) { - if (!parse9(num)) { + if (!parse_const14(num)) { error("failed to evaluate constant expression"); return (false); } @@ -717,11 +855,10 @@ bool const_expr (int *num, char *end1, char *end2) } /* - * pstr - * pstr parses a character than can eventually be 'double' i.e. like 'a9' - * returns 0 in case of failure else 1 + * Test if we have one char enclosed in single quotes + * return 0 in case of failure else 1 */ -bool pstr (int *val) +bool quoted_chr (int *val) { int k; char c; @@ -739,11 +876,11 @@ bool pstr (int *val) } /* - * qstr - * qstr parses a double quoted string into litq - * return 0 in case of failure and 1 else + * Test if we have string enclosed in double quotes. e.g. "abc". + * Load the string into literal pool. + * return 0 in case of failure else 1 */ -bool qstr (int *val) +bool quoted_str (int *val) { char c; diff --git a/src/hucc/primary.h b/src/hucc/primary.h index 651b02c8..3fdb1368 100644 --- a/src/hucc/primary.h +++ b/src/hucc/primary.h @@ -12,8 +12,8 @@ void result (LVALUE lval[], LVALUE lval2[]); int constant (int *val); bool number (int *val); bool const_expr (int *num, char *, char *); -bool pstr (int *val); -bool qstr (int *val); +bool quoted_chr (int *val); +bool quoted_str (int *val); bool const_str (int *val, const char *str); bool readqstr (void); bool readstr (void); diff --git a/src/hucc/stmt.c b/src/hucc/stmt.c index 95cfca62..a27c1341 100644 --- a/src/hucc/stmt.c +++ b/src/hucc/stmt.c @@ -370,15 +370,14 @@ void doswitch (void) ws[WS_STACK_OFFSET] = stkp; ws[WS_TYPE] = WS_SWITCH; ws[WS_CASE_INDEX] = swstp; - ws[WS_TABLE_LABEL] = getlabel(); + ws[WS_SWITCH_LABEL] = getlabel(); ws[WS_DEFAULT_LABEL] = ws[WS_EXIT_LABEL] = getlabel(); addwhile(ws); needbracket("("); expression(YES); needbracket(")"); - gswitch(ws[WS_TABLE_LABEL]); + jump(ws[WS_SWITCH_LABEL]); statement(NO); - ptr = readswitch(); jump(ptr[WS_EXIT_LABEL]); @@ -386,13 +385,16 @@ void doswitch (void) ptr[WS_DEFAULT_LABEL] = getlabel(); auto_default = true; } + gnlabel(ptr[WS_SWITCH_LABEL]); + dumpswitch(ptr); + if (auto_default) { gnlabel((int)ptr[WS_DEFAULT_LABEL]); - out_ins(I_CASE, 0, 0); + out_ins(I_DEFAULT, 0, 0); } - gnlabel(ptr[WS_EXIT_LABEL]); + locsym_index = ptr[WS_LOCSYM_INDEX]; stkp = modstk(ptr[WS_STACK_OFFSET]); swstp = ptr[WS_CASE_INDEX]; @@ -404,15 +406,11 @@ void doswitch (void) */ void docase (void) { - int val; - char n[NAMESIZE]; - - val = 0; + int val = 0; if (readswitch()) { - if (!number(&val)) - if (!pstr(&val)) - if (!(symname(n) && find_enum(n, &val))) - error("bad case label"); + if (!const_expr(&val, ":", NULL)) { + error("case label must be constant"); + } addcase(val); if (!match(":")) error("missing colon"); @@ -432,7 +430,7 @@ void dodefault (void) ptr = readswitch(); if (ptr) { ptr[WS_DEFAULT_LABEL] = lab = getlabel(); - gcase(lab, INT_MAX); + gdefault(lab); if (!match(":")) error("missing colon"); } @@ -577,7 +575,9 @@ void dumpswitch (int *ws) { int i, j, column; - gnlabel(ws[WS_TABLE_LABEL]); + i = getlabel(); + gswitch(i); + gnlabel(i); flush_ins(); i = ws[WS_CASE_INDEX]; diff --git a/src/hucc/sym.c b/src/hucc/sym.c index 4e2ae5c9..6bb216b7 100644 --- a/src/hucc/sym.c +++ b/src/hucc/sym.c @@ -43,7 +43,7 @@ static int init (char *symbol_name, int type, int identity, int *dim, TAG_SYMBOL return (0); } - if (qstr(&value)) { + if (quoted_str(&value)) { if ((identity == VARIABLE) || (type != CCHAR && type != CUCHAR)) error("found string: must assign to char pointer or array"); /* XXX: make this a warning? */ if (identity == POINTER) { @@ -65,7 +65,7 @@ static int init (char *symbol_name, int type, int identity, int *dim, TAG_SYMBOL add_data_initials(symbol_name, CINT, value, tag); *dim = *dim - 1; } - else if (qstr(&value)) { + else if (quoted_str(&value)) { add_data_initials(symbol_name, CCHAR, value, tag); *dim = *dim - 1; } diff --git a/src/mkit/as/assemble.c b/src/mkit/as/assemble.c index 95036097..ba6906e0 100644 --- a/src/mkit/as/assemble.c +++ b/src/mkit/as/assemble.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/src/mkit/as/atari.c b/src/mkit/as/atari.c index 5733f69c..a76628fb 100644 --- a/src/mkit/as/atari.c +++ b/src/mkit/as/atari.c @@ -1,4 +1,5 @@ #include +#include #include #include "defs.h" #include "externs.h" diff --git a/src/mkit/as/code.c b/src/mkit/as/code.c index 8696dde3..c456d895 100644 --- a/src/mkit/as/code.c +++ b/src/mkit/as/code.c @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -89,7 +90,7 @@ class1(int *ip) /* generate code */ if (pass == LAST_PASS) { /* opcode */ - putbyte(data_loccnt, opval); + putbyte(data_loccnt, opval, CODE_OUT); /* output line */ println(); @@ -135,19 +136,19 @@ class2(int *ip) /* long-branch opcode */ if ((opval & 0x1F) == 0x10) { /* conditional-branch */ - putbyte(data_loccnt + 0, opval ^ 0x20); - putbyte(data_loccnt + 1, 0x03); + putbyte(data_loccnt + 0, opval ^ 0x20, CODE_OUT); + putbyte(data_loccnt + 1, 0x03, CODE_OUT); - putbyte(data_loccnt + 2, 0x4C); - putword(data_loccnt + 3, value & 0xFFFF); + putbyte(data_loccnt + 2, 0x4C, CODE_OUT); + putword(data_loccnt + 3, value & 0xFFFF, CODE_OUT); } else { /* bra and bsr */ - putbyte(data_loccnt + 0, (opval == 0x80) ? 0x4C : 0x20); - putword(data_loccnt + 1, value & 0xFFFF); + putbyte(data_loccnt + 0, (opval == 0x80) ? 0x4C : 0x20, CODE_OUT); + putword(data_loccnt + 1, value & 0xFFFF, CODE_OUT); } } else { /* short-branch opcode */ - putbyte(data_loccnt, opval); + putbyte(data_loccnt, opval, CODE_OUT); /* calculate branch offset */ addr = (value & 0xFFFF) - (loccnt + (page << 13) + phase_offset); @@ -159,7 +160,7 @@ class2(int *ip) } /* offset */ - putbyte(data_loccnt + 1, addr); + putbyte(data_loccnt + 1, addr, CODE_OUT); } /* output line */ @@ -185,8 +186,8 @@ class3(int *ip) /* generate code */ if (pass == LAST_PASS) { /* opcodes */ - putbyte(data_loccnt, opval); - putbyte(data_loccnt + 1, optype); + putbyte(data_loccnt, opval, CODE_OUT); + putbyte(data_loccnt + 1, optype, CODE_OUT); /* output line */ println(); @@ -262,8 +263,8 @@ class4(int *ip) /* auto-tag */ if (auto_tag) { if (pass == LAST_PASS) { - putbyte(loccnt, 0xA0); - putbyte(loccnt + 1, auto_tag_value); + putbyte(loccnt, 0xA0, CODE_OUT); + putbyte(loccnt + 1, auto_tag_value, CODE_OUT); } loccnt += 2; } @@ -273,7 +274,7 @@ class4(int *ip) case ACC: /* one byte */ if (pass == LAST_PASS) - putbyte(loccnt, opval); + putbyte(loccnt, opval, CODE_OUT); loccnt++; break; @@ -287,8 +288,8 @@ class4(int *ip) case ZP_IND_Y: /* two bytes */ if (pass == LAST_PASS) { - putbyte(loccnt, opval); - putbyte(loccnt + 1, value); + putbyte(loccnt, opval, CODE_OUT); + putbyte(loccnt + 1, value, CODE_OUT); } loccnt += 2; break; @@ -298,10 +299,14 @@ class4(int *ip) case ABS_Y: case ABS_IND: case ABS_IND_X: + /* remember what labels are function calls */ + if (opval == 0x20 && expr_lablptr != NULL) + expr_lablptr->flags |= FLG_FUNC; + /* three bytes */ if (pass == LAST_PASS) { - putbyte(loccnt, opval); - putword(loccnt + 1, value); + putbyte(loccnt, opval, CODE_OUT); + putword(loccnt + 1, value, CODE_OUT); } loccnt += 3; break; @@ -310,7 +315,7 @@ class4(int *ip) /* auto-increment */ if (auto_inc) { if (pass == LAST_PASS) - putbyte(loccnt, auto_inc); + putbyte(loccnt, auto_inc, CODE_OUT); loccnt += 1; } @@ -360,16 +365,16 @@ class5(int *ip) if (pass == LAST_PASS) { if ((branch) && (branch->convert)) { /* long-branch opcode */ - putbyte(data_loccnt, opval ^ 0x80); - putbyte(data_loccnt + 1, zp); - putbyte(data_loccnt + 2, 0x03); + putbyte(data_loccnt, opval ^ 0x80, CODE_OUT); + putbyte(data_loccnt + 1, zp, CODE_OUT); + putbyte(data_loccnt + 2, 0x03, CODE_OUT); - putbyte(data_loccnt + 3, 0x4C); - putword(data_loccnt + 4, value & 0xFFFF); + putbyte(data_loccnt + 3, 0x4C, CODE_OUT); + putword(data_loccnt + 4, value & 0xFFFF, CODE_OUT); } else { /* short-branch opcode */ - putbyte(data_loccnt, opval); - putbyte(data_loccnt + 1, zp); + putbyte(data_loccnt, opval, CODE_OUT); + putbyte(data_loccnt + 1, zp, CODE_OUT); /* calculate branch offset */ addr = (value & 0xFFFF) - (loccnt + (page << 13) + phase_offset); @@ -381,7 +386,7 @@ class5(int *ip) } /* offset */ - putbyte(data_loccnt + 2, addr); + putbyte(data_loccnt + 2, addr, CODE_OUT); } /* output line */ @@ -421,10 +426,10 @@ class6(int *ip) /* generate code */ if (pass == LAST_PASS) { /* opcodes */ - putbyte(data_loccnt, opval); - putword(data_loccnt + 1, addr[0]); - putword(data_loccnt + 3, addr[1]); - putword(data_loccnt + 5, addr[2]); + putbyte(data_loccnt, opval, CODE_OUT); + putword(data_loccnt + 1, addr[0], CODE_OUT); + putword(data_loccnt + 3, addr[1], CODE_OUT); + putword(data_loccnt + 5, addr[2], CODE_OUT); /* output line */ println(); @@ -467,15 +472,15 @@ class7(int *ip) /* generate code */ if (pass == LAST_PASS) { /* opcodes */ - putbyte(loccnt, opval); - putbyte(loccnt + 1, imm); + putbyte(loccnt, opval, CODE_OUT); + putbyte(loccnt + 1, imm, CODE_OUT); if (mode & (ZP | ZP_X)) /* zero page */ - putbyte(loccnt + 2, addr); + putbyte(loccnt + 2, addr, CODE_OUT); else /* absolute */ - putword(loccnt + 2, addr); + putword(loccnt + 2, addr, CODE_OUT); } /* update location counter */ @@ -487,7 +492,7 @@ class7(int *ip) /* auto-increment */ if (auto_inc) { if (pass == LAST_PASS) - putbyte(loccnt, auto_inc); + putbyte(loccnt, auto_inc, CODE_OUT); loccnt += 1; } @@ -526,8 +531,8 @@ class8(int *ip) } /* opcodes */ - putbyte(data_loccnt, opval); - putbyte(data_loccnt + 1, (1 << value)); + putbyte(data_loccnt, opval, CODE_OUT); + putbyte(data_loccnt + 1, (1 << value), CODE_OUT); /* output line */ println(); @@ -570,8 +575,8 @@ class9(int *ip) } /* opcodes */ - putbyte(data_loccnt, opval + (bit << 4)); - putbyte(data_loccnt + 1, value); + putbyte(data_loccnt, opval + (bit << 4), CODE_OUT); + putbyte(data_loccnt + 1, value, CODE_OUT); /* output line */ println(); @@ -631,16 +636,16 @@ class10(int *ip) if ((branch) && (branch->convert)) { /* long-branch opcode */ - putbyte(data_loccnt, (opval + (bit << 4)) ^ 0x80); - putbyte(data_loccnt + 1, zp); - putbyte(data_loccnt + 2, 0x03); + putbyte(data_loccnt, (opval + (bit << 4)) ^ 0x80, CODE_OUT); + putbyte(data_loccnt + 1, zp, CODE_OUT); + putbyte(data_loccnt + 2, 0x03, CODE_OUT); - putbyte(data_loccnt + 3, 0x4C); - putword(data_loccnt + 4, value & 0xFFFF); + putbyte(data_loccnt + 3, 0x4C, CODE_OUT); + putword(data_loccnt + 4, value & 0xFFFF, CODE_OUT); } else { /* short-branch opcode */ - putbyte(data_loccnt, opval + (bit << 4)); - putbyte(data_loccnt + 1, zp); + putbyte(data_loccnt, opval + (bit << 4), CODE_OUT); + putbyte(data_loccnt + 1, zp, CODE_OUT); /* calculate branch offset */ addr = (value & 0xFFFF) - (loccnt + (page << 13) + phase_offset); @@ -652,7 +657,7 @@ class10(int *ip) } /* offset */ - putbyte(data_loccnt + 2, addr); + putbyte(data_loccnt + 2, addr, CODE_OUT); } /* output line */ diff --git a/src/mkit/as/command.c b/src/mkit/as/command.c index e1683dd3..af1cc46f 100644 --- a/src/mkit/as/command.c +++ b/src/mkit/as/command.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -90,7 +91,8 @@ unsigned short pseudo_allowed[] = { /* P_3PASS */ IN_CODE + IN_HOME + IN_DATA + IN_ZP + IN_BSS, /* P_ALIAS */ IN_CODE + IN_HOME + IN_DATA + IN_ZP + IN_BSS, /* P_REF */ IN_CODE + IN_HOME + IN_DATA + IN_ZP + IN_BSS, -/* P_PHASE */ IN_CODE + IN_HOME +/* P_PHASE */ IN_CODE + IN_HOME, +/* P_LINE */ ANYWHERE }; @@ -363,7 +365,7 @@ do_db(int *ip) /* store char on last pass */ if (pass == LAST_PASS) { /* store character */ - putbyte(loccnt, c); + putbyte(loccnt, c, DATA_OUT); } /* update location counter */ @@ -400,7 +402,7 @@ do_db(int *ip) } /* store byte */ - putbyte(loccnt - 1, value); + putbyte(loccnt - 1, value, DATA_OUT); } } @@ -492,7 +494,7 @@ do_dw(int *ip) } /* store word */ - putword(loccnt - 2, value); + putword(loccnt - 2, value, DATA_OUT); } /* check if there's another word */ @@ -575,7 +577,7 @@ do_dwl(int *ip) } /* store word */ - putbyte(loccnt - 1, (value & 0xff)); + putbyte(loccnt - 1, (value & 0xff), DATA_OUT); } /* check if there's another word */ @@ -658,7 +660,7 @@ do_dwh(int *ip) } /* store word */ - putbyte(loccnt - 1, ((value >> 8) & 0xff)); + putbyte(loccnt - 1, ((value >> 8) & 0xff), DATA_OUT); } /* check if there's another word */ @@ -797,7 +799,7 @@ do_equ(int *ip) } /* get value */ - if (!evaluate(ip, ';', 1)) + if (!evaluate(ip, 0, 1)) return; /* check for undefined symbols - they are only allowed in the FIRST_PASS */ @@ -812,6 +814,38 @@ do_equ(int *ip) /* assign value to the label */ labldef(CONSTANT + optype); /* or VARIABLE */ + /* check for a 2nd parameter */ + if (prlnbuf[*ip] == ',') { + /* skip spaces */ + while (isspace(prlnbuf[++(*ip)])) {} + + if (strncmp(&prlnbuf[*ip], "CODE", 4) == 0 || + strncmp(&prlnbuf[*ip], "code", 4) == 0) { + *ip += 4; + lablptr->data_type = -1; + lablptr->data_size = 0; + lablptr->flags |= FLG_CODE; + } + else + if (strncmp(&prlnbuf[*ip], "FUNC", 4) == 0 || + strncmp(&prlnbuf[*ip], "func", 4) == 0) { + *ip += 4; + lablptr->data_type = -1; + lablptr->data_size = 0; + lablptr->flags |= FLG_CODE + FLG_FUNC; + } + else { + if (!evaluate(ip, 0, 1)) + return; + lablptr->data_type = P_DB; + lablptr->data_size = value; + } + } + + /* check end of line */ + if (!check_eol(ip)) + return; + /* output line */ if (pass == LAST_PASS) { loadlc(value, 1); @@ -1169,6 +1203,9 @@ do_incbin(int *ip) /* load data on last pass */ if (pass == LAST_PASS) { + uint32_t info, *fill_a; + uint8_t *fill_b; + fread(&rom[bank][loccnt], 1, size, fp); if (section == S_DATA && asm_opt[OPT_DATAPAGE] != 0) @@ -1188,6 +1225,14 @@ do_incbin(int *ip) } } + info = debug_info(DATA_OUT); + fill_a = &dbg_info[bank][loccnt]; + fill_b = &dbg_column[bank][loccnt]; + step = size; + while (step--) { + *fill_a++ = info; + *fill_b++ = debug_column; + } /* output line */ println(); } @@ -1347,7 +1392,7 @@ do_mx(char *fname) /* copy data */ if (pass == LAST_PASS) { for (i = 0; i < cnt; i++) - putbyte(loccnt + i, buffer[i]); + putbyte(loccnt + i, buffer[i], DATA_OUT); } /* update location counter */ @@ -1604,6 +1649,9 @@ do_ds(int *ip) /* output line on last pass */ if (pass == LAST_PASS) { + uint32_t info, *fill_a; + uint8_t *fill_b; + if (filler != 0) { if (section == S_ZP) error("Cannot fill .ZP section with non-zero data!"); @@ -1631,6 +1679,15 @@ do_ds(int *ip) left -= step; } } + + info = debug_info(DATA_OUT); + fill_a = &dbg_info[bank][loccnt]; + fill_b = &dbg_column[bank][loccnt]; + step = nbytes; + while (step--) { + *fill_a++ = info; + *fill_b++ = debug_column; + } } } @@ -1930,9 +1987,21 @@ do_align(int *ip) if (section != S_DATA || asm_opt[OPT_DATAPAGE] == 0) page = (page + 1) & 7; } else { - if (section == S_CODE || section == S_DATA) { + if ((section == S_CODE || section == S_DATA) && (bank < UNDEFINED_BANK)) { + uint32_t info, *fill_a; + uint8_t *fill_b; + memset(&rom[bank][oldloc], 0, loccnt - oldloc); memset(&map[bank][oldloc], section + (page << 5), loccnt - oldloc); + + info = debug_info(DATA_OUT); + fill_a = &dbg_info[bank][oldloc]; + fill_b = &dbg_column[bank][oldloc]; + offset = loccnt - oldloc; + while (offset--) { + *fill_a++ = info; + *fill_b++ = debug_column; + } } } } @@ -2430,7 +2499,7 @@ do_alias(int *ip) error("Symbol already used by a label!"); return; } - if (lablptr->reserved) { + if (lablptr->flags & FLG_RESERVED) { error("Reserved symbol!"); return; } @@ -2491,7 +2560,7 @@ do_alias(int *ip) error("Cannot create a .ALIAS to a function!"); return; } - if (alias->reserved) { + if (alias->flags & FLG_RESERVED) { error("Cannot create a .ALIAS to a reserved symbol!"); return; } @@ -2503,6 +2572,7 @@ do_alias(int *ip) /* remember where this was defined */ lablptr->fileinfo = input_file[infile_num].file; lablptr->fileline = slnum; + lablptr->filecolumn = 0; /* the alias needs to inherit any previous references to the label */ alias->refthispass += lablptr->refthispass; @@ -2615,6 +2685,102 @@ do_phase(int *ip) } +/* ---- + * do_debug() + * ---- + * .dbg pseudo for C source code debugging + */ + +void +do_debug(int *ip) +{ + char fname[PATHSZ]; + + /* set label value if there was one */ + labldef(LOCATION); + + /* skip spaces */ + while (isspace(prlnbuf[*ip])) + (*ip)++; + + /* extract type */ + if (!colsym(ip, 0)) { + if (symbol[0] == 0) + fatal_error("Syntax error!"); + return; + } + + if (!strcasecmp(&symbol[1], "line")) { + debug_file = NULL; + debug_line = 0; + debug_column = 0; + + /* get file name */ + if (prlnbuf[*ip] != ',') { + error(".DBG line filename missing!"); + return; + } + ++(*ip); + if (!getstring(ip, fname, PATHSZ - 1)) + return; + + /* get file line */ + if (prlnbuf[*ip] != ',') { + error(".DBG line number missing!"); + return; + } + ++(*ip); + if (!evaluate(ip, 0, 0)) + return; + if (0 > (int)value) { + error(".DBG line number cannot be negative!"); + return; + } + debug_line = value; + + /* get file column (optional) */ + debug_column = 1; + if (prlnbuf[*ip] == ',') { + ++(*ip); + if (!evaluate(ip, 0, 0)) + return; + if (0 > (int)value) { + error(".DBG column number cannot be negative!"); + return; + } + debug_column = value; + } + + debug_file = lookup_file(fname); + if (debug_file == NULL) + return; + + /* check end of line */ + if (!check_eol(ip)) + return; + } + else + if (!strcasecmp(&symbol[1], "clear")) { + debug_file = NULL; + debug_line = 0; + debug_column = 0; + + /* check end of line */ + if (!check_eol(ip)) + return; + } + else { + error("Unknown .DBG type \"%s\"!", &symbol[1]); + return; + } + + /* output line on last pass */ + if (pass == LAST_PASS) { + println(); + } +} + + /* ---- * htoi() * ---- @@ -2646,12 +2812,12 @@ htoi(char *str, int nb) /* ---- - * set_section(int new_section) + * set_section(unsigned char new_section) * ---- */ void -set_section(int new_section) +set_section(unsigned char new_section) { if (section != new_section) { /* backup current section data */ diff --git a/src/mkit/as/defs.h b/src/mkit/as/defs.h index e2353d4e..3824a568 100644 --- a/src/mkit/as/defs.h +++ b/src/mkit/as/defs.h @@ -14,9 +14,11 @@ #if defined(_WIN32) #define PATH_SEPARATOR '\\' #define PATH_SEPARATOR_STRING "\\" +#define WRONG_PATH_SEPARATOR '/' #else #define PATH_SEPARATOR '/' #define PATH_SEPARATOR_STRING "/" +#define WRONG_PATH_SEPARATOR '\\' #endif /* machine */ @@ -39,6 +41,11 @@ /* total number of banks to allocate for workspace */ #define MAX_BANKS (ROM_BANKS + RESERVED_BANKS) +/* type of ROM output for debug_info() */ +#define DATA_OUT 0 +#define FUNC_OUT 1 +#define CODE_OUT 2 + /* tile format for encoder */ #define CHUNKY_TILE 1 #define PACKED_TILE 2 @@ -175,8 +182,9 @@ #define P_ALIAS 66 // .alias #define P_REF 67 // .ref #define P_PHASE 68 // .phase +#define P_DEBUG 69 // .dbg -/* symbol flags */ +/* symbol type */ #define UNDEF 1 /* undefined - may be zero page */ #define IFUNDEF 2 /* declared in a .if expression */ #define MDEF 3 /* multiply defined */ @@ -185,6 +193,11 @@ #define FUNC 6 /* used for a function */ #define ALIAS 7 /* used for an alias */ +/* symbol flags */ +#define FLG_RESERVED 1 +#define FLG_CODE 2 +#define FLG_FUNC 4 + /* symbol lookup flags */ #define SYM_CHK 0 /* does it exist? */ #define SYM_DEF 1 /* symbol definition */ @@ -290,26 +303,27 @@ typedef struct t_symbol { const char *name; struct t_file *fileinfo; int fileline; - int reason; - int type; + int filecolumn; + int deflastpass; + int defthispass; + int reflastpass; + int refthispass; + int rombank; + int mprbank; int value; int phase; - int section; - int overlay; - int mprbank; - int rombank; - int page; int nb; int size; int vram; - int pal; - int reserved; - int data_type; int data_size; - int deflastpass; - int reflastpass; - int defthispass; - int refthispass; + signed char data_type; + unsigned char section; + unsigned char overlay; + unsigned char page; + unsigned char reason; + unsigned char type; + unsigned char flags; + signed char palette; } t_symbol; typedef struct t_branch { diff --git a/src/mkit/as/expr.c b/src/mkit/as/expr.c index 33320f25..c95893d2 100644 --- a/src/mkit/as/expr.c +++ b/src/mkit/as/expr.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "defs.h" @@ -22,26 +23,27 @@ t_symbol pc_symbol = { "\1*", /* name */ NULL, /* fileinfo */ 0, /* fileline */ - CONSTANT, /* reason */ - DEFABS, /* type */ + 0, /* filecolumn */ + 1, /* deflastpass */ + 1, /* defthispass */ + 1, /* reflastpass */ + 1, /* refthispass */ + UNDEFINED_BANK, /* rombank */ + 0, /* mprbank */ 0, /* value */ 0, /* phase */ - S_NONE, /* section */ - 0, /* overlay */ - 0, /* mprbank */ - UNDEFINED_BANK, /* bank */ - 0, /* page */ 0, /* nb */ 0, /* size */ 0, /* vram */ - 0, /* pal */ - 1, /* reserved */ - 0, /* data_type */ 0, /* data_size */ - 1, /* deflastpass */ - 1, /* reflastpass */ - 1, /* defthispass */ - 1 /* refthispass */ + 0, /* data_type */ + S_NONE, /* section */ + 0, /* overlay */ + 0, /* page */ + CONSTANT, /* reason */ + DEFABS, /* type */ + FLG_RESERVED, /* flags */ + 0 /* palette */ }; @@ -611,6 +613,7 @@ push_val(int type) pc_symbol.fileinfo = input_file[infile_num].file; pc_symbol.fileline = slnum; + pc_symbol.filecolumn = 0; /* complicated because loccnt & data_loccnt can be >= $2000 */ if (data_loccnt == -1) @@ -718,9 +721,10 @@ push_val(int type) else { /* resolve newproc procedure labels to their thunk location in the last pass */ struct t_proc *proc; - if ((pass == LAST_PASS) && (newproc_opt != 0) && - ((proc = expr_lablptr->proc) != NULL) && (proc->label == expr_lablptr)) { + ((proc = expr_lablptr->proc) != NULL) && + (proc->label == expr_lablptr) && + (proc->bank != STRIPPED_BANK)) { if (!proc->call) add_thunk(proc); expr_overlay = 0; @@ -728,7 +732,7 @@ push_val(int type) val = proc->call; } else { expr_overlay = expr_lablptr->overlay; - expr_mprbank = expr_lablptr->mprbank; + expr_mprbank = (expr_lablptr->mprbank < UNDEFINED_BANK) ? expr_lablptr->mprbank : UNDEFINED_BANK; val = expr_lablptr->value; } @@ -1175,10 +1179,10 @@ do_op(void) if (!check_func_args("PAL")) return (0); if (pass == LAST_PASS) { - if (expr_lablptr->pal == -1) + if (expr_lablptr->palette == -1) error("No PAL() index for this symbol!"); } - val[0] = expr_lablptr->pal; + val[0] = expr_lablptr->palette; break; /* DEFINED */ diff --git a/src/mkit/as/externs.h b/src/mkit/as/externs.h index 9c587ac1..1e09bb0f 100644 --- a/src/mkit/as/externs.h +++ b/src/mkit/as/externs.h @@ -1,5 +1,8 @@ extern unsigned char rom[MAX_BANKS][8192]; extern unsigned char map[MAX_BANKS][8192]; +extern uint32_t dbg_info[MAX_BANKS][8192]; +extern uint8_t dbg_column[MAX_BANKS][8192]; + extern char bank_name[MAX_BANKS][64]; extern int bank_loccnt[MAX_S][MAX_BANKS]; extern int bank_page[MAX_S][MAX_BANKS]; @@ -22,7 +25,7 @@ extern int page; /* page */ extern int rs_base; /* .rs counter */ extern int rs_mprbank; /* .rs counter */ extern int rs_overlay; /* .rs counter */ -extern int section; /* current section: S_ZP, S_BSS, S_CODE or S_DATA */ +extern unsigned char section; /* current section: S_ZP, S_BSS, S_CODE or S_DATA */ extern int section_bank[MAX_S]; /* current bank for each section */ extern int section_phase[MAX_S]; /* current phase offset for each section */ extern int section_flags[MAX_S]; /* current flags for each section */ @@ -68,6 +71,11 @@ extern int infile_num; extern FILE *out_fp; /* file pointers, output */ extern FILE *in_fp; /* input */ extern FILE *lst_fp; /* listing */ +extern int lst_line; /* listing */ +extern t_file *lst_tfile; /* listing */ +extern int debug_line; /* .DBG info */ +extern int debug_column; /* .DBG info */ +extern t_file *debug_file; /* .DBG info */ extern char *section_name[MAX_S + 1]; extern t_file *extra_file; extern t_input input_file[MAX_NESTING + 1]; @@ -113,6 +121,7 @@ extern int kickc_opt; /* NZ if -kc flag on command lin extern int hucc_opt; /* NZ if -hucc flag on command line */ extern int mlist_opt; /* macro listing main flag */ extern int xlist; /* listing file main flag */ +extern int debug_format; /* debug output type */ extern int list_level; /* output level */ extern int asm_opt[MAX_OPTS]; /* assembler option state */ extern int opvaltab[6][16]; diff --git a/src/mkit/as/func.c b/src/mkit/as/func.c index 4f43ad12..f0fe4b13 100644 --- a/src/mkit/as/func.c +++ b/src/mkit/as/func.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -107,6 +108,7 @@ func_install(int ip) /* remember where this was defined */ lablptr->fileinfo = input_file[infile_num].file; lablptr->fileline = slnum; + lablptr->filecolumn = 0; /* check function name syntax */ if (strchr(&symbol[1], '.')) { diff --git a/src/mkit/as/input.c b/src/mkit/as/input.c index c632127d..9e54f937 100644 --- a/src/mkit/as/input.c +++ b/src/mkit/as/input.c @@ -1,7 +1,9 @@ #include +#include #include #include #include +#include #include #include "defs.h" #include "externs.h" @@ -10,6 +12,7 @@ int file_count; t_str_pool * str_pool; t_file * file_hash[HASH_COUNT]; +t_file ** file_list; #define INCREMENT_BASE 256 #define INCREMENT_BASE_MASK 255 @@ -20,6 +23,7 @@ int infile_num; t_file *extra_file; t_input input_file[MAX_NESTING + 1]; +static char *curpath = NULL; static char *incpath = NULL; static int *incpath_offset = NULL; static int incpath_remaining = 0; @@ -35,11 +39,15 @@ static int incpath_count = 0; void cleanup_path(void) { - if (incpath) + if (incpath) { free(incpath); + incpath = NULL; + } - if (incpath_offset) + if (incpath_offset) { free(incpath_offset); + incpath_offset = NULL; + } } /* ---- @@ -50,6 +58,8 @@ cleanup_path(void) int add_path(char* newpath, int newpath_size) { + char *p; + /* sanity check */ if (newpath_size < 2) return 0; @@ -89,8 +99,12 @@ add_path(char* newpath, int newpath_size) strncpy(incpath + incpath_offset[incpath_count], newpath, newpath_size); incpath[incpath_offset[incpath_count] + newpath_size - 1] = '\0'; - ++incpath_count; + /* Sanitize path */ + p = incpath + incpath_offset[incpath_count]; + while ((p = strchr(p, WRONG_PATH_SEPARATOR)) != NULL) + *p++ = PATH_SEPARATOR; + ++incpath_count; return 1; } @@ -112,6 +126,12 @@ init_path(void) char *p,*pl; int ret, l; + /* Get current working directory */ + if ((curpath = getcwd(NULL, 0)) == NULL || curpath[0] == '(') { + fprintf(stderr, "Unable to get the current directory name\n"); + return 0; + } + /* Get env variable holding PCE path*/ p = getenv(machine->include_env); printf("%s = \"%s\"\n\n", machine->include_env, p); @@ -123,7 +143,6 @@ init_path(void) pl = p; while(pl != NULL) { - /* Jump to next separator */ pl = strchr(p, ENV_PATH_SEPARATOR); @@ -406,7 +425,7 @@ remember_string(const char * string, size_t size) { const char * output; - if ((str_pool == NULL) || (str_pool->remain < size)) { + if ((str_pool == NULL) || (str_pool->remain < (int) size)) { t_str_pool *temp = malloc(sizeof(t_str_pool)); if (temp == NULL) return (NULL); @@ -429,14 +448,14 @@ remember_string(const char * string, size_t size) */ t_file * -remember_file(int hash) +remember_file(const char *name, int hash) { t_file * file = malloc(sizeof(t_file)); if (file == NULL) return (NULL); - file->name = remember_string(full_path, strlen(full_path) + 1); + file->name = remember_string(name, strlen(name) + 1); file->number = ++file_count; file->included = 0; @@ -447,6 +466,41 @@ remember_file(int hash) } +/* ---- + * lookup_file() + * ---- + * lookup file name + */ + +t_file * +lookup_file(const char *name) +{ + int hash; + t_file * file; + + hash = filename_crc(name) & (HASH_COUNT - 1); + file = file_hash[hash]; + while (file) { +#if defined(_WIN32) || defined(__APPLE__) + if (strcasecmp(file->name, name) == 0) + break; +#else + if (strcmp(file->name, name) == 0) + break; +#endif + file = file->next; + } + if (file == NULL) { + file = remember_file(name, hash); + if (file == NULL) { + fatal_error("No memory left to remember filename!"); + return (NULL); + } + } + return file; +} + + /* ---- * clear_included() * ---- @@ -469,6 +523,34 @@ clear_included(void) } +/* ---- + * make_filelist() + * ---- + * create a numerical list of the files used + */ + +void +make_filelist(void) +{ + t_file *file; + int i; + + file_list = calloc(file_count + 1, sizeof(t_file *)); + if (file_list == NULL) { + fprintf(ERROUT, "Error: Cannot create debug filelist!\n"); + exit(1); + } + + for (i = 0; i < HASH_COUNT; i++) { + file = file_hash[i]; + while (file) { + file_list[file->number] = file; + file = file->next; + } + } +} + + /* ---- * open_input() * ---- @@ -482,7 +564,6 @@ open_input(const char *name) char *p; t_file * file; char temp[PATHSZ + 4]; - int hash; /* only MAX_NESTING nested input files */ if (infile_num == MAX_NESTING) { @@ -509,25 +590,10 @@ open_input(const char *name) return (-1); /* remember all filenames */ - hash = filename_crc(full_path) & (HASH_COUNT - 1); - file = file_hash[hash]; - while (file) { -#if defined(_WIN32) || defined(__APPLE__) - if (strcasecmp(file->name, full_path) == 0) - break; -#else - if (strcmp(file->name, full_path) == 0) - break; -#endif - file = file->next; - } + file = lookup_file(full_path); if (file == NULL) { - file = remember_file(hash); - if (file == NULL) { - fclose(fp); - fatal_error("No memory left to remember filename!"); - return (-1); - } + fclose(fp); + return (-1); } /* do not include the same file twice in a pass */ @@ -546,9 +612,14 @@ open_input(const char *name) input_file[infile_num].fp = fp; input_file[infile_num].if_level = if_level; input_file[infile_num].file = file; - if ((pass == LAST_PASS) && (xlist) && (list_level)) + if ((pass == LAST_PASS) && (xlist) && (list_level)) { + fprintf(lst_fp, "%*c", SFIELD-1, ' '); fprintf(lst_fp, "#[%i] \"%s\"\n", infile_num, input_file[infile_num].file->name); - + ++lst_line; + } + debug_file = NULL; + debug_line = 0; + debug_column = 0; /* ok */ return (0); } @@ -587,9 +658,14 @@ close_input(void) infile_error = -1; slnum = input_file[infile_num].lnum; in_fp = input_file[infile_num].fp; - if ((pass == LAST_PASS) && (xlist) && (list_level)) + if ((pass == LAST_PASS) && (xlist) && (list_level)) { + fprintf(lst_fp, "%*c", SFIELD-1, ' '); fprintf(lst_fp, "#[%i] \"%s\"\n", infile_num, input_file[infile_num].file->name); - + ++lst_line; + } + debug_file = NULL; + debug_line = 0; + debug_column = 0; /* ok */ return (0); } @@ -604,12 +680,18 @@ close_input(void) FILE * open_file(const char *name, const char *mode) { - FILE *fileptr; - int i; + FILE *fileptr; + char *p; + int i; fileptr = fopen(name, mode); if (fileptr != NULL) { strcpy(full_path, name); + + p = full_path; + while ((p = strchr(p, WRONG_PATH_SEPARATOR)) != NULL) + *p++ = PATH_SEPARATOR; + return(fileptr); } diff --git a/src/mkit/as/inst.h b/src/mkit/as/inst.h index b114e9b8..7dcf5694 100644 --- a/src/mkit/as/inst.h +++ b/src/mkit/as/inst.h @@ -303,6 +303,7 @@ struct t_opcode base_pseudo[] = { {NULL, ".REF", do_ref, PSEUDO, P_REF, 0}, {NULL, ".PHASE", do_phase, PSEUDO, P_PHASE, 0}, {NULL, ".DEPHASE", do_phase, PSEUDO, P_PHASE, 1}, + {NULL, ".DBG", do_debug, PSEUDO, P_DEBUG, 0}, // pseudo-ops that support asm code generated by KickC diff --git a/src/mkit/as/macro.c b/src/mkit/as/macro.c index d0de488a..fe4614dc 100644 --- a/src/mkit/as/macro.c +++ b/src/mkit/as/macro.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -366,6 +367,7 @@ macro_install(void) /* remember where this was defined */ lablptr->fileinfo = input_file[infile_num].file; lablptr->fileline = slnum; + lablptr->filecolumn = 0; /* check macro name syntax */ /* diff --git a/src/mkit/as/main.c b/src/mkit/as/main.c index 62cd034a..22e11830 100644 --- a/src/mkit/as/main.c +++ b/src/mkit/as/main.c @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -55,6 +56,12 @@ char zeroes[2048]; /* CDROM sector full of zeores */ char *prg_name; /* program name */ FILE *in_fp; /* file pointers, input */ FILE *lst_fp; /* listing */ +int lst_line = 1; /* listing */ +t_file * lst_tfile; /* listing */ +int debug_line; /* .DBG info */ +int debug_column; /* .DBG info */ +t_file *debug_file; /* .DBG info */ + char *section_name[MAX_S + 1] = { "NULL", "ZP", @@ -88,6 +95,7 @@ int sf2_opt; int mx_opt; int mlist_opt; /* macro listing main flag */ int xlist; /* listing file main flag */ +int debug_format; /* debug output type */ int list_level; /* output level */ int asm_opt[MAX_OPTS]; /* assembler options */ int zero_need; /* counter for trailing empty sectors on CDROM */ @@ -278,7 +286,7 @@ main(int argc, char **argv) static t_file *final_source = NULL; static int cd_type; - static const char *cmd_line_options = "I:OShl:mo:s"; + static const char *cmd_line_options = "I:OSg:hl:mo:s"; static const struct option cmd_line_long_options[] = { {"include", required_argument, 0, 'I'}, {"pack", no_argument, 0, 'O'}, @@ -347,6 +355,7 @@ main(int argc, char **argv) } /* init assembler options */ + debug_format = 0; list_level = 2; trim_opt = 0; header_opt = 1; @@ -397,6 +406,23 @@ main(int argc, char **argv) dump_seg = 2; break; + case 'g': + /* optarg can have a leading space on linux/mac */ + while (*optarg == ' ') { ++optarg; } + + /* get debug format */ + debug_format = toupper(*optarg); + + if ((optarg[1] != '\0') || (debug_format != 'C' && debug_format != 'A' && debug_format != 'L')) { + fprintf(stderr, "%s: \"-g\" option must be followed by a 'C', 'A' or 'L'\n", argv[0]); + return (1); + } + if (debug_format == 'L') { + list_level = 2; + mlist_opt = 1; + } + break; + case 'h': help(); return (0); @@ -494,8 +520,8 @@ main(int argc, char **argv) if ((overlayflag == 1) && ((scd_opt == 0) && (cd_opt == 0))) { - fprintf(ERROUT, "Error: Overlay option only valid for CD or SCD programs.\n\n"); help(); + fprintf(ERROUT, "Error: Overlay option only valid for CD or SCD programs.\n\n"); return (1); } } else { @@ -506,6 +532,7 @@ main(int argc, char **argv) /* check for input file name missing */ if (optind == argc) { + help(); fprintf(ERROUT, "Error: Input file name missing!\n"); return (1); } @@ -573,7 +600,17 @@ main(int argc, char **argv) } /* init include path */ - init_path(); + if (!init_path()) { + fprintf(ERROUT, "Error: Unable to initialize include path!\n"); + exit(1); + } + + /* remember the list file now for debug output */ + strcpy(full_path, lst_fname); + lst_tfile = lookup_file(full_path); + if (lst_tfile == NULL) { + exit(1); + } /* open the input file */ if (open_input(in_fname)) { @@ -844,7 +881,9 @@ main(int argc, char **argv) fprintf(ERROUT, "Error: Cannot open listing file \"%s\"!\n", lst_fname); exit(1); } + fprintf(lst_fp, "%*c", SFIELD-1, ' '); fprintf(lst_fp, "#[1] \"%s\"\n", input_file[1].file->name); + ++lst_line; } /* relocate procs */ @@ -1078,7 +1117,11 @@ main(int argc, char **argv) /* dump the symbol table */ if ((fp = fopen(sym_fname, "w")) != NULL) { - labldump(fp); + /* this reorders the symbols, making them unusable for assembling! */ + if (debug_format == 0) + labldump(fp); + else + debugdump(fp); fclose(fp); } @@ -1121,32 +1164,54 @@ help(void) prg_name = machine->asm_name; /* display help */ - printf("%s [options] [-h (for help)] [-o outfile] infiles\n\n", prg_name); - printf("-s : show segment usage\n"); - printf("-S : show segment usage and contents\n"); - printf("-l <0..3> : listing file output level (0-3), default is 2\n"); - printf("-m : force macro expansion in listing\n"); - printf("--raw : prevent adding a ROM header\n"); - printf("--pad : pad ROM size to power-of-two\n"); - printf("--trim : strip unused head and tail from ROM\n"); - printf("-I : add include path\n"); + printf("%s [options] [-o outfile] infiles\n\n", prg_name); + if (machine->type == MACHINE_PCE) { + printf("-gC : output .SYM for mesen2 C source file debugging\n"); + printf("-gA : output .SYM for mesen2 ASM source file debugging\n"); + printf("-gL : output .SYM for mesen2 debugging using .LST file\n"); + printf("-h : display this help message\n"); + printf("-I : add include path\n"); + printf("-l <0..3> : listing file output level (0-3), default is 2\n"); + printf("-m : force macro expansion in listing\n"); + printf("-o : change output ROM/ISO name and extension\n"); + printf("-O : optimize .proc packing (compared to HuC v3.21)\n"); + printf("-s : show segment usage\n"); + printf("-S : show segment usage and contents\n"); + printf("--hucc : set all the options needed for HuCC code\n"); +// printf("--kc : assemble code generated by the KickC compiler\n"); printf("--sf2 : create a StreetFighterII HuCARD\n"); printf("--cd : create a CD-ROM track image\n"); printf("--scd : create a Super CD-ROM track image\n"); + printf("--overlay : create a CD overlay program, not a .ISO\n"); printf("--sgx : add a SuperGRAFX signature to the CD-ROM\n"); - printf("--overlay : create an executable 'overlay' program segment\n"); printf("--ipl : create a custom CD-ROM IPL file\n"); + printf("--raw : prevent adding a ROM header\n"); + printf("--pad : pad ROM size to power-of-two\n"); + printf("--trim : strip unused head and tail from ROM\n"); + printf("--newproc : run .proc code in MPR6, instead of MPR5\n"); + printf("--strip : strip unused .proc & .procgroup\n"); + printf("--srec : create a Motorola S-record file\n"); printf("--develo : assemble and run on the Develo Box\n"); printf("--mx : create a Develo MX file\n"); - printf("-O : optimize .proc packing (compared to HuC v3.21)\n"); - printf("--strip : strip unused .proc & .procgroup\n"); - printf("--newproc : run .proc code in MPR6, instead of MPR5\n"); + printf("infiles : one or more files to be assembled\n"); + printf("\n"); + } else { + printf("-gC : output .SYM for mesen2 C source file debugging\n"); + printf("-gA : output .SYM for mesen2 ASM source file debugging\n"); + printf("-gL : output .SYM for mesen2 debugging using .lst file\n"); + printf("-I : add include path\n"); + printf("-l <0..3> : listing file output level (0-3), default is 2\n"); + printf("-m : force macro expansion in listing\n"); + printf("-s : show segment usage\n"); + printf("-S : show segment usage and contents\n"); + printf("--raw : prevent adding a ROM header\n"); + printf("--pad : pad ROM size to power-of-two\n"); + printf("--trim : strip unused head and tail from ROM\n"); + printf("--srec : create a Motorola S-record file\n"); + printf("infiles : one or more files to be assembled\n"); + printf("\n"); } - printf("--kc : assemble code generated by the KickC compiler\n"); - printf("--srec : create a Motorola S-record file\n"); - printf("infiles : one or more files to be assembled\n"); - printf("\n"); } diff --git a/src/mkit/as/map.c b/src/mkit/as/map.c index 9769e1d3..7569a11d 100644 --- a/src/mkit/as/map.c +++ b/src/mkit/as/map.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "defs.h" diff --git a/src/mkit/as/mml.c b/src/mkit/as/mml.c index 127396a8..5de82d48 100644 --- a/src/mkit/as/mml.c +++ b/src/mkit/as/mml.c @@ -1,4 +1,5 @@ #include +#include #include #include "defs.h" #include "externs.h" diff --git a/src/mkit/as/nes.c b/src/mkit/as/nes.c index 5ee292ec..13a7cd9f 100644 --- a/src/mkit/as/nes.c +++ b/src/mkit/as/nes.c @@ -1,4 +1,5 @@ #include +#include #include #include "defs.h" #include "externs.h" diff --git a/src/mkit/as/output.c b/src/mkit/as/output.c index ace88f6d..0f7b1f69 100644 --- a/src/mkit/as/output.c +++ b/src/mkit/as/output.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "defs.h" #include "externs.h" @@ -36,10 +37,11 @@ println(void) strcpy(prlnbuf, tmplnbuf); /* output */ - if (data_loccnt == -1) + if (data_loccnt == -1) { /* line buffer */ fprintf(lst_fp, "%s\n", prlnbuf); - else { + ++lst_line; + } else { /* line buffer + data bytes */ loadlc(data_loccnt, 0); @@ -49,7 +51,9 @@ println(void) /* check level */ if ((data_level > list_level) && (nb > 4)) { /* doesn't match */ - fputs(prlnbuf, lst_fp); putc('\n', lst_fp); + fputs(prlnbuf, lst_fp); + putc('\n', lst_fp); + ++lst_line; } else { /* ok */ @@ -69,13 +73,17 @@ println(void) cnt++; if (cnt == data_size) { cnt = 0; - fputs(prlnbuf, lst_fp); putc('\n', lst_fp); + fputs(prlnbuf, lst_fp); + putc('\n', lst_fp); + ++lst_line; clearln(); loadlc(data_loccnt, 0); } } if (cnt) { - fputs(prlnbuf, lst_fp); putc('\n', lst_fp); + fputs(prlnbuf, lst_fp); + putc('\n', lst_fp); + ++lst_line; } } } @@ -180,9 +188,10 @@ hexcon(int digit, int num) */ void -putbyte(int offset, int data) +putbyte(int offset, int data, int is_code) { int addr; + uint32_t info; if (((section_flags[section] & S_IS_ROM) == 0) || (bank > bank_limit)) return; @@ -211,6 +220,10 @@ putbyte(int offset, int data) addr = (page << 13) + offset; map[bank][offset] = section + ((addr >> 8) & 0xE0); + + info = debug_info(is_code); + dbg_info[bank][offset] = info; + dbg_column[bank][offset] = debug_column; } @@ -221,9 +234,10 @@ putbyte(int offset, int data) */ void -putword(int offset, int data) +putword(int offset, int data, int is_code) { int addr; + uint32_t info; if (((section_flags[section] & S_IS_ROM) == 0) || (bank > bank_limit)) return; @@ -254,6 +268,12 @@ putword(int offset, int data) map[bank][offset + 0] = section + ((addr++ >> 8) & 0xE0); map[bank][offset + 1] = section + ((addr++ >> 8) & 0xE0); + + info = debug_info(is_code); + dbg_info[bank][offset + 0] = info; + dbg_info[bank][offset + 1] = info; + dbg_column[bank][offset + 0] = debug_column; + dbg_column[bank][offset + 1] = debug_column; } @@ -267,6 +287,7 @@ void putdword(int offset, int data) { int addr; + uint32_t info; if (((section_flags[section] & S_IS_ROM) == 0) || (bank > bank_limit)) return; @@ -301,6 +322,16 @@ putdword(int offset, int data) map[bank][offset + 1] = section + ((addr++ >> 8) & 0xE0); map[bank][offset + 2] = section + ((addr++ >> 8) & 0xE0); map[bank][offset + 3] = section + ((addr++ >> 8) & 0xE0); + + info = debug_info(DATA_OUT); + dbg_info[bank][offset + 0] = info; + dbg_info[bank][offset + 1] = info; + dbg_info[bank][offset + 2] = info; + dbg_info[bank][offset + 3] = info; + dbg_column[bank][offset + 0] = debug_column; + dbg_column[bank][offset + 1] = debug_column; + dbg_column[bank][offset + 2] = debug_column; + dbg_column[bank][offset + 3] = debug_column; } @@ -331,6 +362,9 @@ putbuffer(void *data, int size) /* copy the buffer */ if (pass == LAST_PASS) { + uint32_t info, *fill_a; + uint8_t *fill_b; + if (data) memcpy(&rom[bank][loccnt], data, size); else @@ -351,6 +385,15 @@ putbuffer(void *data, int size) left -= step; } } + + info = debug_info(DATA_OUT); + fill_a = &dbg_info[bank][loccnt]; + fill_b = &dbg_column[bank][loccnt]; + step = size; + while (step--) { + *fill_a++ = info; + *fill_b++ = debug_column; + } } } else { if ((loccnt + size) > section_limit[section]) { diff --git a/src/mkit/as/pce.c b/src/mkit/as/pce.c index 7e0f7f31..b3cee789 100644 --- a/src/mkit/as/pce.c +++ b/src/mkit/as/pce.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "defs.h" @@ -390,7 +391,7 @@ pce_pal(int *ip) error("Incorrect palette index!"); return; } - lastlabl->pal = value; + lastlabl->palette = value; /* output line */ if (pass == LAST_PASS) { @@ -438,7 +439,7 @@ pce_defchr(int *ip) error("Incorrect palette index!"); return; } - lablptr->pal = value; + lablptr->palette = value; } /* get tile data */ @@ -499,7 +500,7 @@ pce_defpal(int *ip) color = (g << 6) + (r << 3) + (b); /* store color */ - putword(loccnt, color); + putword(loccnt, color, DATA_OUT); } /* update location counter */ @@ -560,7 +561,7 @@ pce_defspr(int *ip) error("Incorrect palette index!"); return; } - lablptr->pal = value; + lablptr->palette = value; } /* get sprite data */ @@ -1156,7 +1157,7 @@ pce_incmap(int *ip) /* store tile index */ if (pass == LAST_PASS) - putbyte(loccnt, tile & 0xFF); + putbyte(loccnt, tile & 0xFF, DATA_OUT); /* update location counter */ loccnt++; diff --git a/src/mkit/as/pcx.c b/src/mkit/as/pcx.c index 0f7f471a..5a1391cb 100644 --- a/src/mkit/as/pcx.c +++ b/src/mkit/as/pcx.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -610,7 +611,6 @@ decode_16(FILE *f, int w, int h) pcx_nb_colors = 16; } -#include #pragma pack(1) typedef struct { diff --git a/src/mkit/as/proc.c b/src/mkit/as/proc.c index e56be7c6..f5bf36c6 100644 --- a/src/mkit/as/proc.c +++ b/src/mkit/as/proc.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -140,6 +141,10 @@ do_call(int *ip) if (!evaluate(ip, ';', 0)) return; + /* remember what labels are function calls */ + if (optype == 0 && expr_lablptr != NULL) + expr_lablptr->flags |= FLG_FUNC; + /* generate code */ if (pass == LAST_PASS) { /* lookup proc table */ @@ -178,11 +183,11 @@ do_call(int *ip) /* opcode */ if (optype == 0) - putbyte(data_loccnt, 0x20); /* JSR */ + putbyte(data_loccnt, 0x20, CODE_OUT); /* JSR */ else - putbyte(data_loccnt, 0x4C); /* JMP */ + putbyte(data_loccnt, 0x4C, CODE_OUT); /* JMP */ - putword(data_loccnt+1, value); + putword(data_loccnt+1, value, CODE_OUT); /* output line */ println(); @@ -214,11 +219,11 @@ do_leave(int *ip) if (pass == LAST_PASS) { if (newproc_opt != 0) { /* "jmp" opcode */ - putbyte(data_loccnt, 0x4C); - putword(data_loccnt+1, call_1st - 4); + putbyte(data_loccnt, 0x4C, CODE_OUT); + putword(data_loccnt+1, call_1st - 4, CODE_OUT); } else { /* "rts" opcode */ - putbyte(data_loccnt, 0x60); + putbyte(data_loccnt, 0x60, CODE_OUT); } /* output line */ @@ -391,6 +396,10 @@ do_proc(int *ip) /* define label */ labldef(LOCATION); + /* remember what labels are function calls */ + if (optype != P_PGROUP && lablptr != NULL) + lablptr->flags |= FLG_FUNC; + /* a KickC procedure also opens a label-scope */ if (optype == P_KICKC) { lablptr->scope = scopeptr; @@ -991,12 +1000,14 @@ list_procs(void) struct t_proc *proc_ptr = proc_first; if ((lst_fp != NULL) && (proc_ptr != NULL) && (fprintf(lst_fp, "\nPROCEDURE LIST (in order of size):\n\n") > 0)) { + ++lst_line; while (proc_ptr) { if ((proc_ptr->group == NULL) && (proc_ptr->bank < UNDEFINED_BANK)) { if (fprintf(lst_fp, "Size: $%04X, Addr: $%02X:%04X, %s %s\n", proc_ptr->size, proc_ptr->bank, proc_ptr->label->value, (proc_ptr->type == P_PGROUP) ? ".procgroup" : " .proc" , proc_ptr->label->name + 1) < 0) break; } + ++lst_line; proc_ptr = proc_ptr->link; } } diff --git a/src/mkit/as/protos.h b/src/mkit/as/protos.h index 88c20306..7b5a5f06 100644 --- a/src/mkit/as/protos.h +++ b/src/mkit/as/protos.h @@ -67,8 +67,9 @@ void do_ends(int *ip); void do_alias(int *ip); void do_ref(int *ip); void do_phase(int *ip); +void do_debug(int *ip); int htoi(char *str, int nb); -void set_section(int new_section); +void set_section(unsigned char new_section); /* CRC.C */ unsigned int crc_calc(const unsigned char *data, int len); @@ -97,8 +98,10 @@ void cleanup_path(void); int init_path(void); int readline(void); const char *remember_string(const char * string, size_t length); -t_file *remember_file(int hash); +t_file *remember_file(const char *name, int hash); +t_file *lookup_file(const char *name); void clear_included(void); +void make_filelist(void); int open_input(const char *name); int close_input(void); FILE *open_file(const char *fname, const char *mode); @@ -126,8 +129,8 @@ void println(void); void clearln(void); void loadlc(int offset, int f); void hexcon(int digit, int num); -void putbyte(int offset, int data); -void putword(int offset, int data); +void putbyte(int offset, int data, int is_code); +void putword(int offset, int data, int is_code); void putdword(int offset, int data); void putbuffer(void *data, int size); void write_srec(char *fname, char *ext, int base); @@ -161,17 +164,20 @@ void list_procs(void); int check_thunks(void); /* SYMBOL.C */ +uint32_t debug_info(int is_code); int symhash(void); int addscope(struct t_symbol * curscope, int i); int colsym(int *ip, int flag); struct t_symbol *stlook(int flag); struct t_symbol *stinstall(int hash, int type); -int labldef(int reason); +int labldef(unsigned char reason); void lablset(char *name, int val); int lablexists(char *name); void lablremap(void); +void lablsort(void); void labldump(FILE *fp); +void debugdump(FILE *fp); void lablstartpass(void); -int bank2mprbank (int what_bank, int what_section); -int bank2overlay (int what_bank, int what_section); +int bank2mprbank (int what_bank, unsigned char what_section); +int bank2overlay (int what_bank, unsigned char what_section); int mprbank2bank (int what_bank, int what_overlay); diff --git a/src/mkit/as/symbol.c b/src/mkit/as/symbol.c index 7463983e..0e29c0d4 100644 --- a/src/mkit/as/symbol.c +++ b/src/mkit/as/symbol.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -7,6 +8,27 @@ #include "protos.h" +/* ---- + * debug_info() + * ---- + * calculate the hash value of a symbol + */ + +/* number of bits to shift the source line number */ +#define DBGLINE 12 +#define DBGMASK ((1 << DBGLINE) - 4) + +uint32_t +debug_info(int is_code) +{ + if (debug_format == 'L' && xlist && list_level) + return ((((lst_line << DBGLINE) + (lst_tfile->number << 2)) + is_code)); + if (debug_format == 'C' && debug_file) + return ((((debug_line << DBGLINE) + (debug_file->number << 2)) + is_code)); + return ((((slnum << DBGLINE) + (input_file[infile_num].file->number << 2)) + is_code)); +} + + /* ---- * symhash() * ---- @@ -248,27 +270,27 @@ stinstall(int hash, int type) sym->local = NULL; sym->scope = NULL; sym->proc = NULL; - sym->reason = -1; - sym->type = if_expr ? IFUNDEF : UNDEF; + sym->name = remember_string(symbol, (size_t)symbol[0] + 2); + sym->deflastpass = 0; + sym->reflastpass = 1; /* so that .ifref triggers in 1st pass */ + sym->defthispass = 0; + sym->refthispass = 0; + sym->rombank = UNDEFINED_BANK; + sym->mprbank = UNDEFINED_BANK; sym->value = 0; sym->phase = 0; - sym->section = S_NONE; - sym->overlay = 0; - sym->mprbank = UNDEFINED_BANK; - sym->rombank = UNDEFINED_BANK; - sym->page = -1; sym->nb = 0; sym->size = 0; sym->vram = -1; - sym->pal = -1; - sym->reserved = 0; - sym->data_type = -1; sym->data_size = 0; - sym->deflastpass = 0; - sym->reflastpass = 1; /* so that .ifref triggers in 1st pass */ - sym->defthispass = 0; - sym->refthispass = 0; - sym->name = remember_string(symbol, (size_t)symbol[0] + 2); + sym->data_type = -1; + sym->section = S_NONE; + sym->overlay = 0; + sym->page = 0; + sym->reason = LOCATION; + sym->type = if_expr ? IFUNDEF : UNDEF; + sym->flags = 0; + sym->palette = -1; /* add the symbol to the hash table */ if (type) { @@ -295,10 +317,11 @@ stinstall(int hash, int type) */ int -labldef(int reason) +labldef(unsigned char reason) { char c; - int labl_value, labl_rombank, labl_mprbank, labl_overlay, labl_section; + int labl_value, labl_rombank, labl_mprbank, labl_overlay; + unsigned char labl_section; /* check for NULL ptr */ if (lablptr == NULL) @@ -318,14 +341,27 @@ labldef(int reason) return (-1); } - if (lablptr->reserved) { + if (lablptr->flags & FLG_RESERVED) { fatal_error("Reserved symbol!"); return (-1); } /* remember where this was defined */ - lablptr->fileinfo = input_file[infile_num].file; - lablptr->fileline = slnum; + if (debug_format == 'L' && xlist && list_level) { + lablptr->fileinfo = lst_tfile; + lablptr->fileline = lst_line; + lablptr->filecolumn = 0; + } else { + if (reason == LOCATION && debug_format == 'C' && debug_file) { + lablptr->fileinfo = debug_file; + lablptr->fileline = debug_line; + lablptr->filecolumn = debug_column; + } else { + lablptr->fileinfo = input_file[infile_num].file; + lablptr->fileline = slnum; + lablptr->filecolumn = 0; + } + } if (reason == LOCATION) { /* label is set from the current LOCATION */ @@ -395,7 +431,7 @@ labldef(int reason) if ((lablptr->type == UNDEF) || (lablptr->type == IFUNDEF)) { /* allow the definition */ } - /* don't allow the reason, or the value, to change during a single pass */ + /* don't allow the reason or the value to change during a pass */ else if ((lablptr->reason != reason) || (lablptr->defthispass && lablptr->value != labl_value)) { /* normal label */ @@ -480,7 +516,7 @@ lablset(char *name, int val) lablptr->type = DEFABS; lablptr->value = val; lablptr->defthispass = 1; - lablptr->reserved = 1; + lablptr->flags |= FLG_RESERVED; } } @@ -560,7 +596,119 @@ lablremap(void) /* ---- - * dumplabl() + * lablsort() + * ---- + * sort all label values + * + * THIS IS DESTRUCTIVE AND SHOULD ONLY BE USED JUST PRIOR TO EXITING! + */ + +void +lablsort(void) +{ + struct t_symbol *sort_tbl[HASH_COUNT]; + struct t_symbol *newsym; + struct t_symbol *locsym; + struct t_symbol *nextsym; + struct t_symbol *lastsym; + struct t_symbol *sortsym; + int i, j, bucket; + uint32_t dbginfo; + + memset(sort_tbl, 0, HASH_COUNT * sizeof(struct t_symbol *)); + + /* insertion-sort the symbol table */ + for (i = 0; i < HASH_COUNT; i++) { + for (newsym = hash_tbl[i]; newsym != NULL; newsym = nextsym) { + nextsym = newsym->next; + + /* skip undefined symbols and stripped symbols */ + if ((newsym->type != DEFABS) || (newsym->mprbank == STRIPPED_BANK) || (newsym->name[1] == '!')) + continue; + + if (newsym->mprbank >= 256 && newsym->mprbank != UNDEFINED_BANK) { + printf("WTF is going on!\n"); + exit(1); + continue; + } + + /* mark the first rom byte of every function */ + if (newsym->flags & FLG_FUNC) { + if (newproc_opt && newsym->proc && newsym->proc->label == newsym && newsym->proc->call != 0) { + /* remap procedure name symbols to their thunk address (if it exists) */ + dbginfo = (((newsym->fileline << DBGLINE) + (newsym->fileinfo->number << 2)) + CODE_OUT); + newsym->mprbank = bank2mprbank(call_bank, S_CODE); + newsym->rombank = call_bank; + newsym->value = newsym->proc->call; + /* mark the rom thunk as the start of the procedure's code */ + j = newsym->value & 0x1FFF; + dbg_info[call_bank][j] = dbginfo | FUNC_OUT; + dbg_column[call_bank][j] = 0; + while (++j < ((newsym->value & 0x1FFF) + 10)) { + dbg_info[call_bank][j] = dbginfo; + dbg_column[call_bank][j] = 0; + } + } else { + dbg_info[newsym->rombank][newsym->value & 0x1FFF] |= FUNC_OUT; + } + } + + bucket = newsym->mprbank & (HASH_COUNT - 1); + if (newsym->mprbank == UNDEFINED_BANK) + newsym->mprbank = -1; + + lastsym = NULL; + for (sortsym = sort_tbl[bucket];;) { + if ((sortsym == NULL) || (newsym->overlay < sortsym->overlay) || (newsym->mprbank < sortsym->mprbank) || + ((newsym->overlay == sortsym->overlay) && (newsym->mprbank == sortsym->mprbank) && (newsym->value < sortsym->value))) { + if (lastsym == NULL) { + sort_tbl[bucket] = newsym; + } else { + lastsym->next = newsym; + } + newsym->next = sortsym; + break; + } + lastsym = sortsym; + sortsym = sortsym->next; + } + + /* insertion-sort the local symbols */ + if (newsym->local) { + locsym = newsym->local; + newsym->local = NULL; + + while (locsym) { + if (locsym->mprbank == UNDEFINED_BANK) + locsym->mprbank = -1; + lastsym = NULL; + for (sortsym = newsym->local;;) { + if ((sortsym == NULL) || (locsym->overlay < sortsym->overlay) || (locsym->mprbank < sortsym->mprbank) || + ((locsym->overlay == sortsym->overlay) && (locsym->mprbank == sortsym->mprbank) && (locsym->value < sortsym->value))) { + if (lastsym == NULL) { + newsym->local = locsym; + } else { + lastsym->next = locsym; + } + lastsym = locsym; + locsym = locsym->next; + lastsym->next = sortsym; + break; + } + lastsym = sortsym; + sortsym = sortsym->next; + } + } + } + } + } + + memcpy(hash_tbl, sort_tbl, HASH_COUNT * sizeof(struct t_symbol *)); +} + + +/* ---- + * labldump() * ---- * dump all label values */ @@ -572,6 +720,9 @@ labldump(FILE *fp) struct t_symbol *local; int i; + /* sort the labels for output */ + lablsort(); + fprintf(fp, "Bank\tAddr\tLabel\n"); fprintf(fp, "----\t----\t-----\n"); @@ -583,7 +734,7 @@ labldump(FILE *fp) continue; /* dump the label */ - if (sym->mprbank >= UNDEFINED_BANK) + if (sym->mprbank < 0 || sym->mprbank >= UNDEFINED_BANK) fprintf(fp, " -"); else if (sym->overlay == 0) fprintf(fp, " %2.2x", sym->mprbank); @@ -607,7 +758,7 @@ labldump(FILE *fp) local = sym->local; while (local) { - if (local->mprbank >= UNDEFINED_BANK) + if (local->mprbank < 0 || local->mprbank >= UNDEFINED_BANK) fprintf(fp, " -"); else if (sym->overlay == 0) fprintf(fp, " %2.2x", local->mprbank); @@ -632,6 +783,154 @@ labldump(FILE *fp) } +/* ---- + * debugdump() + * ---- + * dump source-level debugging information for mesen2 + * + * this is a modified form of wla-dx's .sym file info + * has been specifically tailored for use with mesen2. + * + * the original wla-dx .sym file format is here ... + * https://github.com/vhelin/wla-dx/blob/master/doc/symbols.rst + * + * this relies upon the symbol table having already been + * sorted by lablsort() + */ + +extern int file_count; +extern t_file ** file_list; + +void +debugdump(FILE *fp) +{ + struct t_symbol *sym; + int i, j; + + /* sort the labels for output */ + lablsort(); + + /* make a numeric list of the source files */ + make_filelist(); + + fprintf(fp, "; Generated by %s\n\n", machine->asm_name); + fprintf(fp, "[information]\nversion 1\n"); + + /* output the [source-files] section */ + fprintf(fp, "\n[source-files]\n"); + for (i = 0; i <= file_count; i++) { + t_file *file = file_list[i]; + if (file) { + fprintf(fp, "%4.4x \"", i); + /* tell mesen2 to ignore the data columns of the .lst file */ + if (i == 1) + fprintf(fp, "%s\" ; IgnoreColumns=30\n", file->name); + else + fprintf(fp, "%s\"\n", file->name); + } + } + + /* output the [definitions] section */ + fprintf(fp, "\n[definitions]\n"); + for (i = 0; i < 1; i++) { + for (sym = hash_tbl[i]; sym != NULL; sym = sym->next) { + /* only print symbols in the UNDEFINED_BANK */ + if (sym->mprbank >= 0 && sym->mprbank != UNDEFINED_BANK) + continue; + + /* dump the label */ + fprintf(fp, "%8.8x ", sym->value & 0xFFFFFFFF); + fprintf(fp, "%s\n", &(sym->name[1])); + } + } + + /* output the [symbols] section */ + fprintf(fp, "\n[symbols]\n"); + for (i = 0; i < HASH_COUNT; i++) { + for (sym = hash_tbl[i]; sym != NULL; sym = sym->next) { + /* skip undefined symbols and stripped symbols */ + if (sym->mprbank < 0 || sym->mprbank >= UNDEFINED_BANK) + continue; + + /* dump the label */ + if (sym->overlay == 0) + fprintf(fp, "%2.2x", sym->mprbank); + else + fprintf(fp, "%3.3x", (sym->overlay * 0x40) + (sym->mprbank - 0x40) + 0xC0); + fprintf(fp, ":%4.4x ", sym->value & 0xFFFF); + + /* dump the label size if data, else the code/func flags */ + j = 0; + if ((section_flags[sym->section] & S_IS_ROM) && (sym->rombank < UNDEFINED_BANK)) + j = (dbg_info[sym->rombank][sym->value & 0x1FFF] & (CODE_OUT | FUNC_OUT)) << 30; + if (j == 0) + j = sym->data_size & 0xFFFFFFFF; + fprintf(fp, "%8.8x ", j); + fprintf(fp, "%4.4x:%8.8x:%2.2x ", sym->fileinfo->number, sym->fileline, sym->filecolumn); + fprintf(fp, "%s\n", &(sym->name[1])); + } + } + + /* output the [bank-to-source] section */ + { + int bank; + int addr; + int size; + int indx = 0; + int line = 0; + int column = 0; + int code = 0; + uint32_t info; + + fprintf(fp, "\n[bank-to-source]\n"); + for (i = 0; i <= max_bank; i++) { + for (j = 0; j < 0x2000; j++) { + info = dbg_info[i][j]; + if (indx != ((info & DBGMASK) >> 2) || line != (info >> DBGLINE) || + column != dbg_column[i][j] || (code & CODE_OUT) != (info & CODE_OUT)) { + if (indx) { + size = ((i << 13) + j) - ((bank << 13) + addr); + + /* start SFII mapper banks at bank $100 */ + if (bank < 0x80) { + bank += bank_base; + fprintf(fp, "%2.2x:%4.4x ", bank, ((map[bank][addr] >> 5) << 13) + addr); + } else { + bank += 0x80; + fprintf(fp, "%3.3x:%4.4x ", bank, ((map[bank][addr] >> 5) << 13) + addr); + } + + fprintf(fp, "%8.8x ", (code << 30) + size); + fprintf(fp, "%4.4x:%8.8x:%2.2x\n", indx, line, column); + } + bank = i; + addr = j; + indx = (info & DBGMASK) >> 2; + line = (info >> DBGLINE); + code = (info & (CODE_OUT | FUNC_OUT)); + column = dbg_column[i][j]; + } + } + } + if (indx) { + size = ((max_bank + 1) << 13) - ((bank << 13) + addr); + + /* start SFII mapper banks at bank $100 */ + if (bank < 0x80) { + bank += bank_base; + fprintf(fp, "%2.2x:%4.4x ", bank, ((map[bank][addr] >> 5) << 13) + addr); + } else { + bank += 0x80; + fprintf(fp, "%3.3x:%4.4x ", bank, ((map[bank][addr] >> 5) << 13) + addr); + } + + fprintf(fp, "%8.8x ", (code << 30) + size); + fprintf(fp, "%4.4x:%8.8x:%2.2x\n", indx, line, column); + } + } +} + + /* ---- * lablstartpass * ---- @@ -681,7 +980,7 @@ lablstartpass(void) * convert a bank number into a value to put into an MPR register */ -int bank2mprbank (int what_bank, int what_section) +int bank2mprbank (int what_bank, unsigned char what_section) { if ((section_flags[what_section] & S_IS_ROM) && (what_bank < UNDEFINED_BANK)) { if ((section_flags[what_section] & S_IS_SF2) && (what_bank > 0x7F)) { @@ -702,7 +1001,7 @@ int bank2mprbank (int what_bank, int what_section) * convert a bank number into an overlay number */ -int bank2overlay (int what_bank, int what_section) +int bank2overlay (int what_bank, unsigned char what_section) { if ((section_flags[what_section] & S_IS_ROM) && (what_bank < UNDEFINED_BANK)) { if ((section_flags[what_section] & S_IS_SF2) && (what_bank > 0x7F)) { @@ -734,5 +1033,5 @@ int mprbank2bank (int what_bank, int what_overlay) return (what_bank + what_overlay * 0x40); } what_bank = what_bank - bank_base; - return (what_bank <= bank_limit) ? what_bank : UNDEFINED_BANK; + return (what_bank >= 0 && what_bank <= bank_limit) ? what_bank : UNDEFINED_BANK; } diff --git a/src/mkit/as/vars.h b/src/mkit/as/vars.h index 98d213ad..4216d880 100644 --- a/src/mkit/as/vars.h +++ b/src/mkit/as/vars.h @@ -1,5 +1,7 @@ unsigned char rom[MAX_BANKS][8192]; unsigned char map[MAX_BANKS][8192]; +uint32_t dbg_info[MAX_BANKS][8192]; +uint8_t dbg_column[MAX_BANKS][8192]; char bank_name[MAX_BANKS][64]; int bank_loccnt[MAX_S][MAX_BANKS]; int bank_page[MAX_S][MAX_BANKS]; @@ -22,7 +24,7 @@ int page; /* page */ int rs_base; /* .rs counter */ int rs_mprbank; /* .rs counter */ int rs_overlay; /* .rs counter */ -int section; /* current section: S_ZP, S_BSS, S_CODE or S_DATA */ +unsigned char section; /* current section: S_ZP, S_BSS, S_CODE or S_DATA */ int section_bank[MAX_S]; /* current bank for each section */ int section_phase[MAX_S]; /* current phase offset for each section */ int stop_pass; /* stop the program; set by fatal_error() */