OpenCores
URL https://opencores.org/ocsvn/zet86/zet86/trunk

Subversion Repositories zet86

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 25 to Rev 26
    Reverse comparison

Rev 25 → Rev 26

/trunk/rtl-model/alu.v
34,35 → 34,43
wire [8:0] othflags;
wire [19:0] oth;
wire [31:0] cnv, mul;
wire af_add, af_adj;
wire cf_adj, cf_add, cf_mul, cf_log, cf_shi, cf_rot;
wire of_adj, of_add, of_mul, of_log, of_shi, of_rot;
wire af_add, af_cnv;
wire cf_cnv, cf_add, cf_mul, cf_log, cf_shi, cf_rot;
wire of_cnv, of_add, of_mul, of_log, of_shi, of_rot;
wire ofi, sfi, zfi, afi, pfi, cfi;
wire ofo, sfo, zfo, afo, pfo, cfo;
wire flags_unchanged;
 
// Module instances
addsub ad0(x[15:0], y, add, func, word_op, cfi, cf_add, af_add, of_add);
// adj adj0(x[15:0], y, {cf_adj, adj}, func, afi, cfi, af_adj, of_adj);
// conv cnv0(x[15:0], cnv, func[0]);
addsub add1 (x[15:0], y, add, func, word_op, cfi, cf_add, af_add, of_add);
// muldiv mul0(x, y, mul, func[1:0], word_op, cf_mul, of_mul);
bitlog lo0(x[15:0], y, log, func, cf_log, of_log);
shifts sh0(x[15:0], y, shi, func[1:0], word_op, cfi, ofi, cf_shi, of_shi);
rotate rot0(x[15:0], y, func[1:0], cfi, word_op, rot, cf_rot, ofi, of_rot);
othop oth0(x[15:0], y, seg, off, iflags, func, word_op, oth, othflags);
conv cnv2 (
.x (x[15:0]),
.func (func),
.out (cnv),
.iflags ({afi, ofi, cfi}),
.oflags ({af_cnv, of_cnv, cf_cnv})
);
 
mux8_16 m0(t, /* adj */ {8'd0, y[7:0]}, add, cnv[15:0],
bitlog log4 (x[15:0], y, log, func, cf_log, of_log);
shifts shi5 (x[15:0], y, shi, func[1:0], word_op, cfi, ofi, cf_shi, of_shi);
rotate rot6 (x[15:0], y, func[1:0], cfi, word_op, rot, cf_rot, ofi, of_rot);
othop oth7 (x[15:0], y, seg, off, iflags, func, word_op, oth, othflags);
 
mux8_16 m0(t, {8'd0, y[7:0]}, add, cnv[15:0],
mul[15:0], log, shi, rot, oth[15:0], out[15:0]);
mux8_16 m1(t, 16'd0, 16'd0, cnv[31:16], mul[31:16],
16'd0, 16'd0, 16'd0, {12'b0,oth[19:16]}, out[31:16]);
mux8_1 a1(t, cf_adj, cf_add, cfi, cf_mul, cf_log, cf_shi, cf_rot, 1'b0, cfo);
mux8_1 a2(t, af_adj, af_add, afi, 1'b0, 1'b0, 1'b0, afi, 1'b0, afo);
mux8_1 a3(t, of_adj, of_add, ofi, of_mul, of_log, of_shi, of_rot, 1'b0, ofo);
mux8_1 a1(t, cfi, cf_add, cf_cnv, cf_mul, cf_log, cf_shi, cf_rot, 1'b0, cfo);
mux8_1 a2(t, afi, af_add, af_cnv, 1'b0, 1'b0, 1'b0, afi, 1'b0, afo);
mux8_1 a3(t, ofi, of_add, of_cnv, of_mul, of_log, of_shi, of_rot, 1'b0, ofo);
 
// Flags
assign pfo = flags_unchanged ? pfi : ^~ out[7:0];
assign zfo = flags_unchanged ? zfi : (word_op ? ~|out[15:0] : ~|out[7:0]);
assign sfo = flags_unchanged ? sfi : (word_op ? out[15] : out[7]);
assign zfo = flags_unchanged ? zfi
: ((word_op && (t!=3'd2)) ? ~|out[15:0] : ~|out[7:0]);
assign sfo = flags_unchanged ? sfi
: ((word_op && (t!=3'd2)) ? out[15] : out[7]);
 
assign oflags = (t == 3'd7) ? othflags
: { ofo, iflags[10:8], sfo, zfo, afo, pfo, cfo };
74,7 → 82,7
assign pfi = iflags[2];
assign cfi = iflags[0];
 
assign flags_unchanged = (t == 3'd6 || t == 3'd2
assign flags_unchanged = (t == 3'd6
|| t == 3'd4 && func == 4'd2
|| t == 3'd5 && y[7:0] == 8'd0);
endmodule
147,67 → 155,55
assign ofo = word_op ? ofo16 : ofo8;
endmodule
 
module conv (
input [15:0] x,
input [ 2:0] func,
output [31:0] out,
input [ 2:0] iflags, // afi, ofi, cfi
output [ 2:0] oflags // afo, ofo, cfo
);
 
module adj(x, y, out, func, afi, cfi, afo, cfo);
// IO ports
input [15:0] x, y;
input [2:0] func;
input afi, cfi;
output afo, cfo;
output [16:0] out;
 
// Net declarations
wire [15:0] aaa, aad, aam, aas, daa, das, aad16;
wire [7:0] ala, als, alout;
wire alcnd;
wire [4:0] q;
wire [3:0] r;
wire afi, cfi;
wire ofo, afo, cfo;
wire [15:0] aaa, aas;
wire [ 7:0] daa, tmpdaa, das, tmpdas;
wire [15:0] cbw, cwd;
 
wire acond, dcond;
wire tmpcf;
 
// Module instances
mux8_17 m0(func, aaa, aad, aam, aas,
daa, das, {9'd0, y[7:0]}, {1'b0, y}, out);
div10b8 div10 (
.a (x[7:0]),
.q (q),
.r (r)
);
mux8_16 m0(func, cbw, aaa, aas, 16'd0,
cwd, {x[15:8], daa}, {x[15:8], das}, 16'd0, out[15:0]);
 
// Assignments
assign aaa = afo ? { x[15:8] + 8'd1, (x[7:0] + 8'd6) & 8'h0f } : x;
assign aad16 = (x[15:8] << 3) + (x[15:8] << 1) + x[7:0];
assign aad = { 8'b0, aad16[7:0] };
assign aam = { 3'b0, q, 4'b0, r };
assign aas = afo ? { x[15:8] - 8'd1, (x[7:0] - 8'd6) & 8'h0f } : x;
assign aaa = (acond ? (x + 16'h0106) : x) & 16'hff0f;
assign aas = (acond ? (x - 16'h0106) : x) & 16'hff0f;
 
assign ala = afo ? x[7:0] + 8'd6 : x[7:0];
assign als = afo ? x[7:0] - 8'd6 : x[7:0];
assign alout = (func == 3'd4) ? ala : als;
assign alcnd = (alout > 8'h9f) | cfi;
assign daa = alcnd ? { x[15:8], x[3:0] + 8'h60 } : { x[15:8], alout };
assign das = alcnd ? { x[15:8], x[3:0] - 8'h60 } : { x[15:8], alout };
assign tmpdaa = acond ? (x[7:0] + 8'h06) : x[7:0];
assign daa = dcond ? (tmpdaa + 8'h60) : tmpdaa;
assign tmpdas = acond ? (x[7:0] - 8'h06) : x[7:0];
assign das = dcond ? (tmpdas - 8'h60) : tmpdas;
 
assign afo = (x[3:0] > 4'd9) | afi;
assign cfo = func[2] ? alcnd : afo;
endmodule
assign cbw = { { 8{x[ 7]}}, x[7:0] };
assign { out[31:16], cwd } = { {16{x[15]}}, x };
 
module conv(x, out, func);
// IO ports
input [15:0] x;
input func; // type = 010 and func = 111 is reserved for INTO
output [31:0] out;
assign acond = ((x[7:0] & 8'h0f) > 8'h09) | afi;
assign dcond = (x[7:0] > 8'h99) | cfi;
 
// Net declarations
wire [31:0] cbw, cwd;
wire [23:0] x7_24;
wire [15:0] x15_16;
assign afi = iflags[2];
assign cfi = iflags[0];
 
// Assignments
assign x7_24 = { 24{x[7]} };
assign x15_16 = { 16{x[15]} };
assign cbw = { x7_24, x[7:0] };
assign cwd = { x15_16, x[7:0] };
assign out = func ? cwd : cbw;
assign afo = acond;
assign ofo = 1'b0;
assign tmpcf = (x[7:0] < 8'h06) | cfi;
assign cfo = func[2] ? (dcond ? 1'b1 : (acond & tmpcf))
: acond;
 
assign oflags = { afo, ofo, cfo };
endmodule
 
/*
module muldiv(x, y, out, func, word_op, cfo, ofo);
// IO ports
/trunk/rtl-model/fetch.v
417,6 → 417,30
src <= 4'b0;
end
 
8'b0010_0111: // daa
begin
seq_addr <= `DAA;
need_modrm <= 1'b0;
need_off <= 1'b0;
need_imm <= 1'b0;
off_size <= 1'b0;
imm_size <= 1'b0;
dst <= 4'b0;
src <= 4'b0;
end
 
8'b0010_1111: // das
begin
seq_addr <= `DAS;
need_modrm <= 1'b0;
need_off <= 1'b0;
need_imm <= 1'b0;
off_size <= 1'b0;
imm_size <= 1'b0;
dst <= 4'b0;
src <= 4'b0;
end
 
8'b0011_000x: // xor r->r, r->m
begin
seq_addr <= (mod==2'b11) ? (b ? `XORRRB : `XORRRW)
455,6 → 479,30
src <= 4'b0;
end
 
8'b0011_0111: // aaa
begin
seq_addr <= `AAA;
need_modrm <= 1'b0;
need_off <= 1'b0;
need_imm <= 1'b0;
off_size <= 1'b0;
imm_size <= 1'b0;
dst <= 4'b0;
src <= 4'b0;
end
 
8'b0011_1111: // aas
begin
seq_addr <= `AAS;
need_modrm <= 1'b0;
need_off <= 1'b0;
need_imm <= 1'b0;
off_size <= 1'b0;
imm_size <= 1'b0;
dst <= 4'b0;
src <= 4'b0;
end
 
8'b0101_0xxx: // push reg
begin
seq_addr <= `PUSHR;
655,6 → 703,30
dst <= { 1'b0, opcode[2:0] };
end
 
8'b1001_1000: // cbw
begin
seq_addr <= `CBW;
need_modrm <= 1'b0;
need_off <= 1'b0;
need_imm <= 1'b0;
off_size <= 1'b0;
imm_size <= 1'b0;
dst <= 4'b0;
src <= 4'b0;
end
 
8'b1001_1001: // cwd
begin
seq_addr <= `CWD;
need_modrm <= 1'b0;
need_off <= 1'b0;
need_imm <= 1'b0;
off_size <= 1'b0;
imm_size <= 1'b0;
dst <= 4'b0;
src <= 4'b0;
end
 
8'b1001_1010: // call different seg
begin
seq_addr <= `CALLF;
/trunk/tests/i86/.bochsrc
1,4 → 1,4
romimage: file=rot.out
romimage: file=13_bcdcnv.out
cpu: count=1, ips=10000000, reset_on_triple_fault=1
megs: 2
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
/trunk/soc/bios/rombios.h
0,0 → 1,10
#define BIOS_PRINTF_HALT 1
#define BIOS_PRINTF_SCREEN 2
#define BIOS_PRINTF_INFO 4
#define BIOS_PRINTF_DEBUG 8
#define BIOS_PRINTF_ALL (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
#define BIOS_PRINTF_DEBHALT (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT)
 
#define printf(format, p...) bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
#define BX_INFO(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
#define BX_PANIC(format, p...) bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
/trunk/soc/bios/biossums.c
0,0 → 1,504
/*
* $Id: biossums.c,v 1.1 2008-10-01 02:25:51 zeus Exp $
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
 
/* biossums.c --- written by Eike W. for the Bochs BIOS */
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
typedef unsigned char byte;
 
void check( int value, char* message );
 
#define LEN_BIOS_DATA 0x10000
#define MAX_OFFSET (LEN_BIOS_DATA - 1)
 
 
#define BIOS_OFFSET 0xFFFF
 
long chksum_bios_get_offset( byte* data, long offset );
byte chksum_bios_calc_value( byte* data, long offset );
byte chksum_bios_get_value( byte* data, long offset );
void chksum_bios_set_value( byte* data, long offset, byte value );
 
 
#define _32__LEN 9
#define _32__CHKSUM 10
 
#define _32__MINHDR 16
 
long chksum__32__get_offset( byte* data, long offset );
byte chksum__32__calc_value( byte* data, long offset );
byte chksum__32__get_value( byte* data, long offset );
void chksum__32__set_value( byte* data, long offset, byte value );
 
 
#define _MP__LEN 8
#define _MP__CHKSUM 10
 
#define _MP__MINHDR 16
 
long chksum__mp__get_offset( byte* data, long offset );
byte chksum__mp__calc_value( byte* data, long offset );
byte chksum__mp__get_value( byte* data, long offset );
void chksum__mp__set_value( byte* data, long offset, byte value );
 
 
#define PCMP_BASELEN 4
#define PCMP_CHKSUM 7
#define PCMP_EXT_LEN 40
#define PCMP_EXT_CHKSUM 42
 
#define PCMP_MINHDR 42
 
long chksum_pcmp_get_offset( byte* data, long offset );
byte chksum_pcmp_calc_value( byte* data, long offset );
byte chksum_pcmp_get_value( byte* data, long offset );
void chksum_pcmp_set_value( byte* data, long offset, byte value );
 
 
#define _PIR_LEN 6
#define _PIR_CHKSUM 31
 
#define _PIR_MINHDR 32
 
long chksum__pir_get_offset( byte *data, long offset );
byte chksum__pir_calc_value( byte* data, long offset );
byte chksum__pir_get_value( byte* data, long offset );
void chksum__pir_set_value( byte* data, long offset, byte value );
 
 
byte bios_data[LEN_BIOS_DATA];
long bios_len;
 
 
int main(int argc, char* argv[]) {
 
FILE* stream;
long offset, tmp_offset;
byte cur_val = 0, new_val = 0;
int arg = 1, hits, pad = 0;
 
 
if ((argc == 3) && (!strcmp(argv[1], "-pad"))) {
pad = 1;
arg = 2;
} else if (argc != 2) {
printf("Error. Need a file-name as an argument.\n");
exit(EXIT_FAILURE);
}
memset(bios_data, 0xff, LEN_BIOS_DATA);
 
if ((stream = fopen(argv[arg], "rb")) == NULL) {
printf("Error opening %s for reading.\n", argv[arg]);
exit(EXIT_FAILURE);
}
bios_len = fread(bios_data, 1, LEN_BIOS_DATA, stream);
if ((bios_len < LEN_BIOS_DATA) && (pad == 0)) {
printf("Error reading 64KBytes from %s.\n", argv[arg]);
fclose(stream);
exit(EXIT_FAILURE);
}
fclose(stream);
if (pad == 1) goto write_bios;
 
hits = 0;
offset = 0L;
while( (tmp_offset = chksum__32__get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum__32__get_value( bios_data, offset );
new_val = chksum__32__calc_value( bios_data, offset );
printf( "\n\nPCI-Bios header at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum__32__set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Multiple PCI headers! No checksum set." );
}
if( hits ) {
printf( "\n" );
}
 
 
hits = 0;
offset = 0L;
while( (tmp_offset = chksum__mp__get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum__mp__get_value( bios_data, offset );
new_val = chksum__mp__calc_value( bios_data, offset );
printf( "\n\nMP header at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum__mp__set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Warning! Multiple MP headers. No checksum set." );
}
if( hits ) {
printf( "\n" );
}
 
 
hits = 0;
offset = 0L;
while( (tmp_offset = chksum_pcmp_get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum_pcmp_get_value( bios_data, offset );
new_val = chksum_pcmp_calc_value( bios_data, offset );
printf( "\n\nPCMP header at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum_pcmp_set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Warning! Multiple PCMP headers. No checksum set." );
}
if( hits ) {
printf( "\n" );
}
 
 
hits = 0;
offset = 0L;
while( (tmp_offset = chksum__pir_get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum__pir_get_value( bios_data, offset );
new_val = chksum__pir_calc_value( bios_data, offset );
printf( "\n\n$PIR header at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X\n ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum__pir_set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Warning! Multiple $PIR headers. No checksum set." );
}
if( hits ) {
printf( "\n" );
}
 
 
offset = 0L;
offset = chksum_bios_get_offset( bios_data, offset );
cur_val = chksum_bios_get_value( bios_data, offset );
new_val = chksum_bios_calc_value( bios_data, offset );
printf( "\n\nBios checksum at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
if( cur_val != new_val ) {
printf( "Setting checksum." );
chksum_bios_set_value( bios_data, offset, new_val );
}
printf( "\n" );
 
write_bios:
if ((stream = fopen(argv[arg], "wb")) == NULL) {
printf("Error opening %s for writing.\n", argv[arg]);
exit(EXIT_FAILURE);
}
if (fwrite(bios_data, 1, LEN_BIOS_DATA, stream) < LEN_BIOS_DATA) {
printf("Error writing 64KBytes to %s.\n", argv[arg]);
fclose(stream);
exit(EXIT_FAILURE);
}
fclose(stream);
 
return(EXIT_SUCCESS);
}
 
 
void check(int okay, char* message) {
 
if (!okay) {
printf("\n\nError. %s.\n", message);
exit(EXIT_FAILURE);
}
}
 
 
long chksum_bios_get_offset( byte* data, long offset ) {
 
return( BIOS_OFFSET );
}
 
 
byte chksum_bios_calc_value( byte* data, long offset ) {
 
int i;
byte sum;
 
sum = 0;
for( i = 0; i < MAX_OFFSET; i++ ) {
sum = sum + *( data + i );
}
sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
return( sum );
}
 
 
byte chksum_bios_get_value( byte* data, long offset ) {
 
return( *( data + BIOS_OFFSET ) );
}
 
 
void chksum_bios_set_value( byte* data, long offset, byte value ) {
 
*( data + BIOS_OFFSET ) = value;
}
 
 
byte chksum__32__calc_value( byte* data, long offset ) {
 
int i;
int len;
byte sum;
 
check( offset + _32__MINHDR <= MAX_OFFSET, "_32_ header out of bounds" );
len = *( data + offset + _32__LEN ) << 4;
check( offset + len <= MAX_OFFSET, "_32_ header-length out of bounds" );
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != _32__CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
 
 
long chksum__32__get_offset( byte* data, long offset ) {
 
long result = -1L;
 
offset = offset + 0x0F;
offset = offset & ~( 0x0F );
while( offset + 16 < MAX_OFFSET ) {
offset = offset + 16;
if( *( data + offset + 0 ) == '_' && \
*( data + offset + 1 ) == '3' && \
*( data + offset + 2 ) == '2' && \
*( data + offset + 3 ) == '_' ) {
result = offset;
break;
}
}
return( result );
}
 
 
byte chksum__32__get_value( byte* data, long offset ) {
 
check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
return( *( data + offset + _32__CHKSUM ) );
}
 
 
void chksum__32__set_value( byte* data, long offset, byte value ) {
 
check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
*( data + offset + _32__CHKSUM ) = value;
}
 
 
byte chksum__mp__calc_value( byte* data, long offset ) {
 
int i;
int len;
byte sum;
 
check( offset + _MP__MINHDR <= MAX_OFFSET, "_MP_ header out of bounds" );
len = *( data + offset + _MP__LEN ) << 4;
check( offset + len <= MAX_OFFSET, "_MP_ header-length out of bounds" );
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != _MP__CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
 
 
long chksum__mp__get_offset( byte* data, long offset ) {
 
long result = -1L;
 
offset = offset + 0x0F;
offset = offset & ~( 0x0F );
while( offset + 16 < MAX_OFFSET ) {
offset = offset + 16;
if( *( data + offset + 0 ) == '_' && \
*( data + offset + 1 ) == 'M' && \
*( data + offset + 2 ) == 'P' && \
*( data + offset + 3 ) == '_' ) {
result = offset;
break;
}
}
return( result );
}
 
 
byte chksum__mp__get_value( byte* data, long offset ) {
 
check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
return( *( data + offset + _MP__CHKSUM ) );
}
 
 
void chksum__mp__set_value( byte* data, long offset, byte value ) {
 
check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
*( data + offset + _MP__CHKSUM ) = value;
}
 
 
byte chksum_pcmp_calc_value( byte* data, long offset ) {
 
int i;
int len;
byte sum;
 
check( offset + PCMP_MINHDR <= MAX_OFFSET, "PCMP header out of bounds" );
len = *( data + offset + PCMP_BASELEN ) + \
( *( data + offset + PCMP_BASELEN + 1 ) << 8 );
check( offset + len <= MAX_OFFSET, "PCMP header-length out of bounds" );
if( *( data + offset + PCMP_EXT_LEN ) | \
*( data + offset + PCMP_EXT_LEN + 1 ) | \
*( data + offset + PCMP_EXT_CHKSUM ) ) {
check( 0, "PCMP header indicates extended tables (unsupported)" );
}
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != PCMP_CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
 
 
long chksum_pcmp_get_offset( byte* data, long offset ) {
 
long result = -1L;
 
offset = offset + 0x0F;
offset = offset & ~( 0x0F );
while( offset + 16 < MAX_OFFSET ) {
offset = offset + 16;
if( *( data + offset + 0 ) == 'P' && \
*( data + offset + 1 ) == 'C' && \
*( data + offset + 2 ) == 'M' && \
*( data + offset + 3 ) == 'P' ) {
result = offset;
break;
}
}
return( result );
}
 
 
byte chksum_pcmp_get_value( byte* data, long offset ) {
 
check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
return( *( data + offset + PCMP_CHKSUM ) );
}
 
 
void chksum_pcmp_set_value( byte* data, long offset, byte value ) {
 
check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
*( data + offset + PCMP_CHKSUM ) = value;
}
 
 
byte chksum__pir_calc_value( byte* data, long offset ) {
 
int i;
int len;
byte sum;
 
check( offset + _PIR_MINHDR <= MAX_OFFSET, "$PIR header out of bounds" );
len = *( data + offset + _PIR_LEN ) + \
( *( data + offset + _PIR_LEN + 1 ) << 8 );
check( offset + len <= MAX_OFFSET, "$PIR header-length out of bounds" );
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != _PIR_CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
 
 
long chksum__pir_get_offset( byte* data, long offset ) {
 
long result = -1L;
 
offset = offset + 0x0F;
offset = offset & ~( 0x0F );
while( offset + 16 < MAX_OFFSET ) {
offset = offset + 16;
if( *( data + offset + 0 ) == '$' && \
*( data + offset + 1 ) == 'P' && \
*( data + offset + 2 ) == 'I' && \
*( data + offset + 3 ) == 'R' ) {
result = offset;
break;
}
}
return( result );
}
 
 
byte chksum__pir_get_value( byte* data, long offset ) {
 
check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
return( *( data + offset + _PIR_CHKSUM ) );
}
 
 
void chksum__pir_set_value( byte* data, long offset, byte value ) {
 
check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
*( data + offset + _PIR_CHKSUM ) = value;
}
 
/trunk/soc/bios/makesym.perl
0,0 → 1,31
#!/usr/bin/perl
#
# $Id: makesym.perl,v 1.1 2008-10-01 02:25:51 zeus Exp $
#
# Read output file from as86 (e.g. rombios.txt) and write out a symbol
# table suitable for the Bochs debugger.
#
 
$WHERE_BEFORE_SYM_TABLE = 0;
$WHERE_IN_SYM_TABLE = 1;
$WHERE_AFTER_SYM_TABLE = 2;
 
$where = $WHERE_BEFORE_SYM_TABLE;
while (<STDIN>) {
chop;
if ($where == WHERE_BEFORE_SYM_TABLE && /^Symbols:/) {
$where = $WHERE_IN_SYM_TABLE;
} elsif ($where == $WHERE_IN_SYM_TABLE && /^$/) {
$where = $WHERE_AFTER_SYM_TABLE;
}
if ($where == $WHERE_IN_SYM_TABLE) {
@F = split (/\s+/);
($name[0], $junk, $addr[0], $junk, $name[1], $junk, $addr[1]) = @F;
foreach $col (0,1) {
next if length $addr[$col] < 1;
$addr[$col] =~ tr/A-Z/a-z/;
$addr[$col] = "000f" . $addr[$col];
print "$addr[$col] $name[$col]\n";
}
}
}
trunk/soc/bios/makesym.perl Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/soc/bios/rombios.c =================================================================== --- trunk/soc/bios/rombios.c (nonexistent) +++ trunk/soc/bios/rombios.c (revision 26) @@ -0,0 +1,1332 @@ +// ROM BIOS compatability entry points: +// =================================== +// $e05b ; POST Entry Point +// $e6f2 ; INT 19h Boot Load Service Entry Point +// $f045 ; INT 10 Functions 0-Fh Entry Point +// $f065 ; INT 10h Video Support Service Entry Point +// $f0a4 ; MDA/CGA Video Parameter Table (INT 1Dh) +// $fff0 ; Power-up Entry Point +// $fff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY +// $fffe ; System Model ID + +#include "rombios.h" + + /* model byte 0xFC = AT */ +#define SYS_MODEL_ID 0xFC + +#ifndef BIOS_BUILD_DATE +# define BIOS_BUILD_DATE "06/23/99" +#endif + + // 1K of base memory used for Extended Bios Data Area (EBDA) + // EBDA is used for PS/2 mouse support, and IDE BIOS, etc. +#define EBDA_SEG 0x9FC0 +#define EBDA_SIZE 1 // In KiB +#define BASE_MEM_IN_K (640 - EBDA_SIZE) + +/* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */ +#define IPL_SEG 0x9ff0 +#define IPL_TABLE_OFFSET 0x0000 +#define IPL_TABLE_ENTRIES 8 +#define IPL_COUNT_OFFSET 0x0080 /* u16: number of valid table entries */ +#define IPL_SEQUENCE_OFFSET 0x0082 /* u16: next boot device */ +#define IPL_BOOTFIRST_OFFSET 0x0084 /* u16: user selected device */ +#define IPL_SIZE 0xff +#define IPL_TYPE_FLOPPY 0x01 +#define IPL_TYPE_HARDDISK 0x02 +#define IPL_TYPE_CDROM 0x03 +#define IPL_TYPE_BEV 0x80 + +// This is for compiling with gcc2 and gcc3 +#define ASM_START #asm +#define ASM_END #endasm + +ASM_START +.rom + +.org 0x0000 + +use16 8086 + +MACRO SET_INT_VECTOR + mov ax, ?3 + mov ?1*4, ax + mov ax, ?2 + mov ?1*4+2, ax +MEND + +ASM_END + +typedef unsigned char Bit8u; +typedef unsigned short Bit16u; +typedef unsigned short bx_bool; +typedef unsigned long Bit32u; + + + void memsetb(seg,offset,value,count); + void memcpyb(dseg,doffset,sseg,soffset,count); + void memcpyd(dseg,doffset,sseg,soffset,count); + + // memset of count bytes + void + memsetb(seg,offset,value,count) + Bit16u seg; + Bit16u offset; + Bit16u value; + Bit16u count; + { + ASM_START + push bp + mov bp, sp + + push ax + push cx + push es + push di + + mov cx, 10[bp] ; count + test cx, cx + je memsetb_end + mov ax, 4[bp] ; segment + mov es, ax + mov ax, 6[bp] ; offset + mov di, ax + mov al, 8[bp] ; value + cld + rep + stosb + + memsetb_end: + pop di + pop es + pop cx + pop ax + + pop bp + ASM_END + } + + // memcpy of count bytes + void + memcpyb(dseg,doffset,sseg,soffset,count) + Bit16u dseg; + Bit16u doffset; + Bit16u sseg; + Bit16u soffset; + Bit16u count; + { + ASM_START + push bp + mov bp, sp + + push ax + push cx + push es + push di + push ds + push si + + mov cx, 12[bp] ; count + test cx, cx + je memcpyb_end + mov ax, 4[bp] ; dsegment + mov es, ax + mov ax, 6[bp] ; doffset + mov di, ax + mov ax, 8[bp] ; ssegment + mov ds, ax + mov ax, 10[bp] ; soffset + mov si, ax + cld + rep + movsb + + memcpyb_end: + pop si + pop ds + pop di + pop es + pop cx + pop ax + + pop bp + ASM_END + } + + // Bit32u (unsigned long) and long helper functions + ASM_START + + idiv_u: + xor dx,dx + div bx + ret + + ldivul: + mov cx,[di] + mov di,2[di] + call ludivmod + xchg ax,cx + xchg bx,di + ret + +.align 2 +ldivmod: + mov dx,di ; sign byte of b in dh + mov dl,bh ; sign byte of a in dl + test di,di + jns set_asign + neg di + neg cx + sbb di,*0 +set_asign: + test bx,bx + jns got_signs ; leave r = a positive + neg bx + neg ax + sbb bx,*0 + j got_signs + +.align 2 +ludivmod: + xor dx,dx ; both sign bytes 0 +got_signs: + push bp + push si + mov bp,sp + push di ; remember b + push cx +b0 = -4 +b16 = -2 + + test di,di + jne divlarge + test cx,cx + je divzero + cmp bx,cx + jae divlarge ; would overflow + xchg dx,bx ; a in dx:ax, signs in bx + div cx + xchg cx,ax ; q in di:cx, junk in ax + xchg ax,bx ; signs in ax, junk in bx + xchg ax,dx ; r in ax, signs back in dx + mov bx,di ; r in bx:ax + j zdivu1 + +divzero: ; return q = 0 and r = a + test dl,dl + jns return + j negr ; a initially minus, restore it + +divlarge: + push dx ; remember sign bytes + mov si,di ; w in si:dx, initially b from di:cx + mov dx,cx + xor cx,cx ; q in di:cx, initially 0 + mov di,cx + ; r in bx:ax, initially a + ; use di:cx rather than dx:cx in order + ; to have dx free for a byte pair later + cmp si,bx + jb loop1 + ja zdivu ; finished if b > r + cmp dx,ax + ja zdivu + +; rotate w (= b) to greatest dyadic multiple of b <= r + +loop1: + shl dx,*1 ; w = 2*w + rcl si,*1 + jc loop1_exit ; w was > r counting overflow (unsigned) + cmp si,bx ; while w <= r (unsigned) + jb loop1 + ja loop1_exit + cmp dx,ax + jbe loop1 ; else exit with carry clear for rcr +loop1_exit: + rcr si,*1 + rcr dx,*1 +loop2: + shl cx,*1 ; q = 2*q + rcl di,*1 + cmp si,bx ; if w <= r + jb loop2_over + ja loop2_test + cmp dx,ax + ja loop2_test +loop2_over: + add cx,*1 ; q++ + adc di,*0 + sub ax,dx ; r = r-w + sbb bx,si +loop2_test: + shr si,*1 ; w = w/2 + rcr dx,*1 + cmp si,b16[bp] ; while w >= b + ja loop2 + jb zdivu + cmp dx,b0[bp] + jae loop2 + +zdivu: + pop dx ; sign bytes +zdivu1: + test dh,dh + js zbminus + test dl,dl + jns return ; else a initially minus, b plus + mov dx,ax ; -a = b * q + r ==> a = b * (-q) + (-r) + or dx,bx + je negq ; use if r = 0 + sub ax,b0[bp] ; use a = b * (-1 - q) + (b - r) + sbb bx,b16[bp] + not cx ; q = -1 - q (same as complement) + not di +negr: + neg bx + neg ax + sbb bx,*0 +return: + mov sp,bp + pop si + pop bp + ret + +.align 2 +zbminus: + test dl,dl ; (-a) = (-b) * q + r ==> a = b * q + (-r) + js negr ; use if initial a was minus + mov dx,ax ; a = (-b) * q + r ==> a = b * (-q) + r + or dx,bx + je negq ; use if r = 0 + sub ax,b0[bp] ; use a = b * (-1 - q) + (b + r) + ; (b is now -b) + sbb bx,b16[bp] + not cx + not di + mov sp,bp + pop si + pop bp + ret + +.align 2 +negq: + neg di + neg cx + sbb di,*0 + mov sp,bp + pop si + pop bp + ret + +.align 2 +ltstl: +ltstul: + test bx,bx + je ltst_not_sure + ret + +.align 2 +ltst_not_sure: + test ax,ax + js ltst_fix_sign + ret + +.align 2 +ltst_fix_sign: + inc bx + ret + +.align 2 +lmull: +lmulul: + mov cx,ax + mul word ptr 2[di] + xchg ax,bx + mul word ptr [di] + add bx,ax + mov ax,ptr [di] + mul cx + add bx,dx + ret + +.align 2 +lsubl: +lsubul: + sub ax,[di] + sbb bx,2[di] + ret + +.align 2 +laddl: +laddul: + add ax,[di] + adc bx,2[di] + ret + +.align 2 +lorl: +lorul: + or ax,[di] + or bx,2[di] + ret + +.align 2 +lsrul: + mov cx,di + jcxz lsru_exit + cmp cx,*32 + jae lsru_zero +lsru_loop: + shr bx,*1 + rcr ax,*1 + loop lsru_loop +lsru_exit: + ret + +.align 2 +lsru_zero: + xor ax,ax + mov bx,ax + ret + +.align 2 +landl: +landul: + and ax,[di] + and bx,2[di] + ret + +.align 2 +lcmpl: +lcmpul: + sub bx,2[di] + je lcmp_not_sure + ret + +.align 2 +lcmp_not_sure: + cmp ax,[di] + jb lcmp_b_and_lt + jge lcmp_exit + + inc bx +lcmp_exit: + ret + +.align 2 +lcmp_b_and_lt: + dec bx + ret + + ASM_END + +typedef struct { + Bit16u type; + Bit16u flags; + Bit32u vector; + Bit32u description; + Bit32u reserved; + } ipl_entry_t; + + + +static Bit8u inb_cmos(); + +static Bit8u read_byte(); +static Bit16u read_word(); +static void write_byte(); +static void write_word(); +static void bios_printf(); + +static void int19_function(); +static Bit16u get_CS(); +static Bit16u get_SS(); + +static void print_bios_banner(); +static void print_boot_device(); + + Bit8u +inb_cmos(cmos_reg) + Bit8u cmos_reg; +{ +ASM_START + push bp + mov bp, sp + + mov al, 4[bp] ;; cmos_reg + out 0x70, al + in al, 0x71 + + pop bp +ASM_END +} + + Bit8u +read_byte(seg, offset) + Bit16u seg; + Bit16u offset; +{ +ASM_START + push bp + mov bp, sp + + push bx + push ds + mov ax, 4[bp] ; segment + mov ds, ax + mov bx, 6[bp] ; offset + mov al, [bx] + ;; al = return value (byte) + pop ds + pop bx + + pop bp +ASM_END +} + + Bit16u +read_word(seg, offset) + Bit16u seg; + Bit16u offset; +{ +ASM_START + push bp + mov bp, sp + + push bx + push ds + mov ax, 4[bp] ; segment + mov ds, ax + mov bx, 6[bp] ; offset + mov ax, [bx] + ;; ax = return value (word) + pop ds + pop bx + + pop bp +ASM_END +} + + void +write_byte(seg, offset, data) + Bit16u seg; + Bit16u offset; + Bit8u data; +{ +ASM_START + push bp + mov bp, sp + + push ax + push bx + push ds + mov ax, 4[bp] ; segment + mov ds, ax + mov bx, 6[bp] ; offset + mov al, 8[bp] ; data byte + mov [bx], al ; write data byte + pop ds + pop bx + pop ax + + pop bp +ASM_END +} + + void +write_word(seg, offset, data) + Bit16u seg; + Bit16u offset; + Bit16u data; +{ +ASM_START + push bp + mov bp, sp + + push ax + push bx + push ds + mov ax, 4[bp] ; segment + mov ds, ax + mov bx, 6[bp] ; offset + mov ax, 8[bp] ; data word + mov [bx], ax ; write data word + pop ds + pop bx + pop ax + + pop bp +ASM_END +} + + Bit16u +get_CS() +{ +ASM_START + mov ax, cs +ASM_END +} + + Bit16u +get_SS() +{ +ASM_START + mov ax, ss +ASM_END +} + + void +wrch(c) + Bit8u c; +{ + ASM_START + push bp + mov bp, sp + + push bx + mov ah, #0x0e + mov al, 4[bp] + xor bx,bx + int #0x10 + pop bx + + pop bp + ASM_END +} + + void +send(action, c) + Bit16u action; + Bit8u c; +{ + if (action & BIOS_PRINTF_SCREEN) { + if (c == '\n') wrch('\r'); + wrch(c); + } +} + + void +put_int(action, val, width, neg) + Bit16u action; + short val, width; + bx_bool neg; +{ + short nval = val / 10; + if (nval) + put_int(action, nval, width - 1, neg); + else { + while (--width > 0) send(action, ' '); + if (neg) send(action, '-'); + } + send(action, val - (nval * 10) + '0'); +} + + void +put_uint(action, val, width, neg) + Bit16u action; + unsigned short val; + short width; + bx_bool neg; +{ + unsigned short nval = val / 10; + if (nval) + put_uint(action, nval, width - 1, neg); + else { + while (--width > 0) send(action, ' '); + if (neg) send(action, '-'); + } + send(action, val - (nval * 10) + '0'); +} + + void +put_luint(action, val, width, neg) + Bit16u action; + unsigned long val; + short width; + bx_bool neg; +{ + unsigned long nval = val / 10; + if (nval) + put_luint(action, nval, width - 1, neg); + else { + while (--width > 0) send(action, ' '); + if (neg) send(action, '-'); + } + send(action, val - (nval * 10) + '0'); +} + +void put_str(action, segment, offset) + Bit16u action; + Bit16u segment; + Bit16u offset; +{ + Bit8u c; + + while (c = read_byte(segment, offset)) { + send(action, c); + offset++; + } +} + +//-------------------------------------------------------------------------- +// bios_printf() +// A compact variable argument printf function. +// +// Supports %[format_width][length]format +// where format can be x,X,u,d,s,S,c +// and the optional length modifier is l (ell) +//-------------------------------------------------------------------------- + void +bios_printf(action, s) + Bit16u action; + Bit8u *s; +{ + Bit8u c, format_char; + bx_bool in_format; + short i; + Bit16u *arg_ptr; + Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width, hexadd; + + arg_ptr = &s; + arg_seg = get_SS(); + + in_format = 0; + format_width = 0; + + if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) + bios_printf (BIOS_PRINTF_SCREEN, "FATAL: "); + + while (c = read_byte(get_CS(), s)) { + if ( c == '%' ) { + in_format = 1; + format_width = 0; + } + else if (in_format) { + if ( (c>='0') && (c<='9') ) { + format_width = (format_width * 10) + (c - '0'); + } + else { + arg_ptr++; // increment to next arg + arg = read_word(arg_seg, arg_ptr); + if (c == 'x' || c == 'X') { + if (format_width == 0) + format_width = 4; + if (c == 'x') + hexadd = 'a'; + else + hexadd = 'A'; + for (i=format_width-1; i>=0; i--) { + nibble = (arg >> (4 * i)) & 0x000f; + send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd)); + } + } + else if (c == 'u') { + put_uint(action, arg, format_width, 0); + } + else if (c == 'l') { + s++; + c = read_byte(get_CS(), s); /* is it ld,lx,lu? */ + arg_ptr++; /* increment to next arg */ + hibyte = read_word(arg_seg, arg_ptr); + if (c == 'd') { + if (hibyte & 0x8000) + put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), format_width-1, 1); + else + put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); + } + else if (c == 'u') { + put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); + } + else if (c == 'x' || c == 'X') + { + if (format_width == 0) + format_width = 8; + if (c == 'x') + hexadd = 'a'; + else + hexadd = 'A'; + for (i=format_width-1; i>=0; i--) { + nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f; + send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd)); + } + } + } + else if (c == 'd') { + if (arg & 0x8000) + put_int(action, -arg, format_width - 1, 1); + else + put_int(action, arg, format_width, 0); + } + else if (c == 's') { + put_str(action, get_CS(), arg); + } + else if (c == 'S') { + hibyte = arg; + arg_ptr++; + arg = read_word(arg_seg, arg_ptr); + put_str(action, hibyte, arg); + } + else if (c == 'c') { + send(action, arg); + } + else + BX_PANIC("bios_printf: unknown format\n"); + in_format = 0; + } + } + else { + send(action, c); + } + s ++; + } + + if (action & BIOS_PRINTF_HALT) { + // freeze in a busy loop. +ASM_START + cli + halt2_loop: + hlt + jmp halt2_loop +ASM_END + } +} + +static char bios_svn_version_string[] = "$Revision: 1.1 $ $Date: 2008-10-01 02:25:51 $"; + +//-------------------------------------------------------------------------- +// print_bios_banner +// displays a the bios version +//-------------------------------------------------------------------------- +void +print_bios_banner() +{ + printf("Zet BIOS - build: %s\n%s\n", + BIOS_BUILD_DATE, bios_svn_version_string); +} + +//-------------------------------------------------------------------------- +// BIOS Boot Specification 1.0.1 compatibility +// +// Very basic support for the BIOS Boot Specification, which allows expansion +// ROMs to register themselves as boot devices, instead of just stealing the +// INT 19h boot vector. +// +// This is a hack: to do it properly requires a proper PnP BIOS and we aren't +// one; we just lie to the option ROMs to make them behave correctly. +// We also don't support letting option ROMs register as bootable disk +// drives (BCVs), only as bootable devices (BEVs). +// +// http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm +//-------------------------------------------------------------------------- + +static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"}; + +static void +init_boot_vectors() +{ + ipl_entry_t e; + Bit16u count = 0; + Bit16u ss = get_SS(); + + /* Clear out the IPL table. */ + memsetb(IPL_SEG, IPL_TABLE_OFFSET, 0, IPL_SIZE); + + /* User selected device not set */ + write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF); + + /* + * Zet: We don't have support for floppy, hdd or cdrom + */ + + /* Remember how many devices we have */ + write_word(IPL_SEG, IPL_COUNT_OFFSET, count); + /* Not tried booting anything yet */ + write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff); +} + +static Bit8u +get_boot_vector(i, e) +Bit16u i; ipl_entry_t *e; +{ + Bit16u count; + Bit16u ss = get_SS(); + /* Get the count of boot devices, and refuse to overrun the array */ + count = read_word(IPL_SEG, IPL_COUNT_OFFSET); + if (i >= count) return 0; + /* OK to read this device */ + memcpyb(ss, e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (*e), sizeof (*e)); + return 1; +} + +//-------------------------------------------------------------------------- +// print_boot_device +// displays the boot device +//-------------------------------------------------------------------------- + +void +print_boot_device(e) + ipl_entry_t *e; +{ + Bit16u type; + char description[33]; + Bit16u ss = get_SS(); + type = e->type; + /* NIC appears as type 0x80 */ + if (type == IPL_TYPE_BEV) type = 0x4; + if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n"); + printf("Booting from %s", drivetypes[type]); + /* print product string if BEV */ + if (type == 4 && e->description != 0) { + /* first 32 bytes are significant */ + memcpyb(ss, &description, (Bit16u)(e->description >> 16), (Bit16u)(e->description & 0xffff), 32); + /* terminate string */ + description[32] = 0; + printf(" [%S]", ss, description); + } + printf("...\n"); +} + +void +int19_function(seq_nr) +Bit16u seq_nr; +{ + Bit16u ebda_seg=read_word(0x0040,0x000E); + Bit16u bootdev; + Bit8u bootdrv; + Bit8u bootchk; + Bit16u bootseg; + Bit16u bootip; + Bit16u status; + Bit16u bootfirst; + + ipl_entry_t e; + + // Here we assume that BX_ELTORITO_BOOT is defined, so + // CMOS regs 0x3D and 0x38 contain the boot sequence: + // CMOS reg 0x3D & 0x0f : 1st boot device + // CMOS reg 0x3D & 0xf0 : 2nd boot device + // CMOS reg 0x38 & 0xf0 : 3rd boot device + // boot device codes: + // 0x00 : not defined + // 0x01 : first floppy + // 0x02 : first harddrive + // 0x03 : first cdrom + // 0x04 - 0x0f : PnP expansion ROMs (e.g. Etherboot) + // else : boot failure + + // Get the boot sequence + bootdev = inb_cmos(0x3d); + bootdev |= ((inb_cmos(0x38) & 0xf0) << 4); + bootdev >>= 4 * seq_nr; + bootdev &= 0xf; + + /* Read user selected device */ + bootfirst = read_word(IPL_SEG, IPL_BOOTFIRST_OFFSET); + if (bootfirst != 0xFFFF) { + bootdev = bootfirst; + /* User selected device not set */ + write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF); + /* Reset boot sequence */ + write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xFFFF); + } else if (bootdev == 0) BX_PANIC("No bootable device.\n"); + + /* Translate from CMOS runes to an IPL table offset by subtracting 1 */ + bootdev -= 1; + + /* Read the boot device from the IPL table */ + if (get_boot_vector(bootdev, &e) == 0) { + BX_INFO("Invalid boot device (0x%x)\n", bootdev); + return; + } + + /* Do the loading, and set up vector as a far pointer to the boot + * address, and bootdrv as the boot drive */ + print_boot_device(&e); + + switch(e.type) { + case IPL_TYPE_BEV: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */ + bootseg = e.vector >> 16; + bootip = e.vector & 0xffff; + break; + + default: return; + } + + /* Debugging info */ + BX_INFO("Booting from %x:%x\n", bootseg, bootip); + + /* Jump to the boot vector */ +ASM_START + mov bp, sp + ;; Build an iret stack frame that will take us to the boot vector. + ;; iret pops ip, then cs, then flags, so push them in the opposite order. + pushf + mov ax, _int19_function.bootseg + 0[bp] + push ax + mov ax, _int19_function.bootip + 0[bp] + push ax + ;; Set the magic number in ax and the boot drive in dl. + mov ax, #0xaa55 + mov dl, _int19_function.bootdrv + 0[bp] + ;; Zero some of the other registers. + xor bx, bx + mov ds, bx + mov es, bx + mov bp, bx + ;; Go! + iret +ASM_END +} + +ASM_START +;---------- +;- INT18h - +;---------- +int18_handler: ;; Boot Failure recovery: try the next device. + + ;; Reset SP and SS + mov ax, #0xfffe + mov sp, ax + xor ax, ax + mov ss, ax + + ;; Get the boot sequence number out of the IPL memory + mov bx, #IPL_SEG + mov ds, bx ;; Set segment + mov bx, IPL_SEQUENCE_OFFSET ;; BX is now the sequence number + inc bx ;; ++ + mov IPL_SEQUENCE_OFFSET, bx ;; Write it back + mov ds, ax ;; and reset the segment to zero. + + ;; Carry on in the INT 19h handler, using the new sequence number + push bx + + jmp int19_next_boot + +;---------- +;- INT19h - +;---------- +int19_relocated: ;; Boot function, relocated + + ;; int19 was beginning to be really complex, so now it + ;; just calls a C function that does the work + + push bp + mov bp, sp + + ;; Reset SS and SP + mov ax, #0xfffe + mov sp, ax + xor ax, ax + mov ss, ax + + ;; Start from the first boot device (0, in AX) + mov bx, #IPL_SEG + mov ds, bx ;; Set segment to write to the IPL memory + mov IPL_SEQUENCE_OFFSET, ax ;; Save the sequence number + mov ds, ax ;; and reset the segment. + + push ax + +int19_next_boot: + + ;; Call the C code for the next boot device + call _int19_function + + ;; Boot failed: invoke the boot recovery function + int #0x18 + +;-------------------- +;- POST: EBDA segment +;-------------------- +; relocated here because the primary POST area isnt big enough. +ebda_post: +#if BX_USE_EBDA + mov ax, #EBDA_SEG + mov ds, ax + mov byte ptr [0x0], #EBDA_SIZE +#endif + xor ax, ax ; mov EBDA seg into 40E + mov ds, ax + mov word ptr [0x40E], #EBDA_SEG + ret;; + +rom_checksum: + push ax + push bx + push cx + xor ax, ax + xor bx, bx + xor cx, cx + mov ch, [2] + shl cx, #1 +checksum_loop: + add al, [bx] + inc bx + loop checksum_loop + and al, #0xff + pop cx + pop bx + pop ax + ret + + +;; We need a copy of this string, but we are not actually a PnP BIOS, +;; so make sure it is *not* aligned, so OSes will not see it if they scan. +.align 16 + db 0 +pnp_string: + .ascii "$PnP" + + +rom_scan: + ;; Scan for existence of valid expansion ROMS. + ;; Video ROM: from 0xC0000..0xC7FFF in 2k increments + ;; General ROM: from 0xC8000..0xDFFFF in 2k increments + ;; System ROM: only 0xE0000 + ;; + ;; Header: + ;; Offset Value + ;; 0 0x55 + ;; 1 0xAA + ;; 2 ROM length in 512-byte blocks + ;; 3 ROM initialization entry point (FAR CALL) + +rom_scan_loop: + push ax ;; Save AX + mov ds, cx + mov ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k + cmp [0], #0xAA55 ;; look for signature + jne rom_scan_increment + call rom_checksum + jnz rom_scan_increment + mov al, [2] ;; change increment to ROM length in 512-byte blocks + + ;; We want our increment in 512-byte quantities, rounded to + ;; the nearest 2k quantity, since we only scan at 2k intervals. + test al, #0x03 + jz block_count_rounded + and al, #0xfc ;; needs rounding up + add al, #0x04 +block_count_rounded: + + xor bx, bx ;; Restore DS back to 0000: + mov ds, bx + push ax ;; Save AX + push di ;; Save DI + ;; Push addr of ROM entry point + push cx ;; Push seg + push #0x0003 ;; Push offset + + ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS. + ;; That should stop it grabbing INT 19h; we will use its BEV instead. + mov ax, #0xf000 + mov es, ax + lea di, pnp_string + + mov bp, sp ;; Call ROM init routine using seg:off on stack + db 0xff ;; call_far ss:[bp+0] + db 0x5e + db 0 + cli ;; In case expansion ROM BIOS turns IF on + add sp, #2 ;; Pop offset value + pop cx ;; Pop seg value (restore CX) + + ;; Look at the ROM's PnP Expansion header. Properly, we're supposed + ;; to init all the ROMs and then go back and build an IPL table of + ;; all the bootable devices, but we can get away with one pass. + mov ds, cx ;; ROM base + mov bx, 0x001a ;; 0x1A is the offset into ROM header that contains... + mov ax, [bx] ;; the offset of PnP expansion header, where... + cmp ax, #0x5024 ;; we look for signature "$PnP" + jne no_bev + mov ax, 2[bx] + cmp ax, #0x506e + jne no_bev + mov ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of... + cmp ax, #0x0000 ;; the Bootstrap Entry Vector, or zero if there is none. + je no_bev + + ;; Found a device that thinks it can boot the system. Record its BEV and product name string. + mov di, 0x10[bx] ;; Pointer to the product name string or zero if none + mov bx, #IPL_SEG ;; Go to the segment where the IPL table lives + mov ds, bx + mov bx, IPL_COUNT_OFFSET ;; Read the number of entries so far + cmp bx, #IPL_TABLE_ENTRIES + je no_bev ;; Get out if the table is full + push cx + mov cx, #0x4 ;; Zet: Needed to be compatible with 8086 + shl bx, cl ;; Turn count into offset (entries are 16 bytes) + pop cx + mov 0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device + mov 6[bx], cx ;; Build a far pointer from the segment... + mov 4[bx], ax ;; and the offset + cmp di, #0x0000 + je no_prod_str + mov 0xA[bx], cx ;; Build a far pointer from the segment... + mov 8[bx], di ;; and the offset +no_prod_str: + push cx + mov cx, #0x4 + shr bx, cl ;; Turn the offset back into a count + pop cx + inc bx ;; We have one more entry now + mov IPL_COUNT_OFFSET, bx ;; Remember that. + +no_bev: + pop di ;; Restore DI + pop ax ;; Restore AX +rom_scan_increment: + push cx + mov cx, #5 + shl ax, cl ;; convert 512-bytes blocks to 16-byte increments + ;; because the segment selector is shifted left 4 bits. + pop cx + add cx, ax + pop ax ;; Restore AX + cmp cx, ax + jbe rom_scan_loop + + xor ax, ax ;; Restore DS back to 0000: + mov ds, ax + ret + +;; for 'C' strings and other data, insert them here with +;; a the following hack: +;; DATA_SEG_DEFS_HERE + + +;; the following area can be used to write dynamically generated tables + .align 16 +bios_table_area_start: + dd 0xaafb4442 + dd bios_table_area_end - bios_table_area_start - 8; + +;-------- +;- POST - +;-------- +.org 0xe05b ; POST Entry Point +post: + + xor ax, ax + +normal_post: + ; case 0: normal startup + + cli + mov ax, #0xfffe + mov sp, ax + xor ax, ax + mov ds, ax + mov ss, ax + + ;; zero out BIOS data area (40:00..40:ff) + mov es, ax + mov cx, #0x0080 ;; 128 words + mov di, #0x0400 + cld + rep + stosw + + ;; set all interrupts to default handler + xor bx, bx ;; offset index + mov cx, #0x0100 ;; counter (256 interrupts) + mov ax, #dummy_iret_handler + mov dx, #0xF000 + +post_default_ints: + mov [bx], ax + add bx, #2 + mov [bx], dx + add bx, #2 + loop post_default_ints + + ;; set vector 0x79 to zero + ;; this is used by 'gardian angel' protection system + SET_INT_VECTOR(0x79, #0, #0) + + ;; base memory in K 40:13 (word) + mov ax, #BASE_MEM_IN_K + mov 0x0413, ax + + + ;; Manufacturing Test 40:12 + ;; zerod out above + + ;; Warm Boot Flag 0040:0072 + ;; value of 1234h = skip memory checks + ;; zerod out above + + ;; Bootstrap failure vector + SET_INT_VECTOR(0x18, #0xF000, #int18_handler) + + ;; Bootstrap Loader vector + SET_INT_VECTOR(0x19, #0xF000, #int19_handler) + + ;; EBDA setup + call ebda_post + + ;; Video setup + SET_INT_VECTOR(0x10, #0xF000, #int10_handler) + + mov cx, #0xc000 ;; init vga bios + mov ax, #0xc780 + call rom_scan + + call _print_bios_banner + + call _init_boot_vectors + + mov cx, #0xc800 ;; init option roms + mov ax, #0xe000 + call rom_scan + + sti ;; enable interrupts + int #0x19 + +;---------- +;- INT19h - +;---------- +.org 0xe6f2 ; INT 19h Boot Load Service Entry Point +int19_handler: + + jmp int19_relocated + +.org 0xf045 ; INT 10 Functions 0-Fh Entry Point + ;; HALT(__LINE__) + iret + +;---------- +;- INT10h - +;---------- +.org 0xf065 ; INT 10h Video Support Service Entry Point +int10_handler: + ;; dont do anything, since the VGA BIOS handles int10h requests + iret + +.org 0xf0a4 ; MDA/CGA Video Parameter Table (INT 1Dh) + +;------------------------------------------------ +;- IRET Instruction for Dummy Interrupt Handler - +;------------------------------------------------ +.org 0xff53 ; IRET Instruction for Dummy Interrupt Handler +dummy_iret_handler: + iret + +.org 0xfff0 ; Power-up Entry Point + jmp 0xf000:post + +.org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY +.ascii BIOS_BUILD_DATE + +.org 0xfffe ; System Model ID +db SYS_MODEL_ID +db 0x00 ; filler +ASM_END + +ASM_START +.org 0xcc00 +bios_table_area_end: +// bcc-generated data will be placed here +ASM_END Index: trunk/soc/bios/Makefile =================================================================== --- trunk/soc/bios/Makefile (nonexistent) +++ trunk/soc/bios/Makefile (revision 26) @@ -0,0 +1,54 @@ +.SUFFIXES: .cc + +srcdir = . + + +SHELL = /bin/sh + + + +CXX = g++ +CXXFLAGS = -g3 -O0 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES + +LDFLAGS = +LIBS = -lm +RANLIB = ranlib + +BCC = bcc +GCC = gcc +GCC32 = gcc -m32 +AS86 = as86 + +BX_INCDIRS = -I.. -I$(srcdir)/.. -I../iodev -I$(srcdir)/../iodev +LOCAL_CXXFLAGS = + +BUILDDATE = `date '+%m/%d/%y'` +BIOS_BUILD_DATE = "-DBIOS_BUILD_DATE=\"$(BUILDDATE)\"" +# +# -------- end configurable options -------------------------- +# + +bios: biossums zet-bios + +clean: + rm -f *.o *.a *.s _rombios*_.c rombios*.txt rombios*.sym + rm -f usage biossums + +bios-clean: + rm -f zet-bios + +.cc.o: + $(CXX) -c $(BX_INCDIRS) $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@ + +zet-bios: rombios.c biossums rombios.h + $(GCC32) $(BIOS_BUILD_DATE) -DLEGACY -E -P $< > _rombiosl_.c + $(BCC) -o rombiosl.s -C-c -D__i86__ -0 -S _rombiosl_.c + sed -e 's/^\.text//' -e 's/^\.data//' rombiosl.s > _rombiosl_.s + $(AS86) _rombiosl_.s -b tmpl.bin -u- -w- -g -0 -j -O -l rombiosl.txt + -perl ${srcdir}/makesym.perl < rombiosl.txt > rombiosl.sym + mv tmpl.bin $@ + ./biossums $@ + rm -f _rombiosl_.s + +biossums: biossums.c + $(GCC) -o biossums biossums.c \ No newline at end of file Index: trunk/sim/memory.v =================================================================== --- trunk/sim/memory.v (revision 25) +++ trunk/sim/memory.v (revision 26) @@ -24,5 +24,5 @@ if (we) if (byte_m) ram[addr] <= wr_data[7:0]; else { ram[addr1], ram[addr] } <= wr_data; - initial $readmemh("/home/zeus/zet/sim/12_rotate.rtlrom", ram, 20'hf0000); + initial $readmemh("/home/zeus/zet/sim/13_bcdcnv.rtlrom", ram, 20'hf0000); endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.